1 Introduction

This document largely follows the structure / manuscript plan set our in Laura’s email from 30 November 2022.

Where the narrative set out in that email conflicted with the results, this report was amended accordingly.

2 Abbreviations

CBD - cerebrovascular disease

CRF - case report form

CVD - cardiovascular disease

GLM - Generalised Linear Model; basically the standard regression models, including linear, logistic and Poisson regression models as special cases.

LMM - Linear Mixed Models; a generalisation of linear regression models to longitdunal / panel data; repated measurements for each individual are accommodated throught he specification of a correlation structure and random effects for subject-specific effects.

LTFU - Lost to follow-up or Loss to follow-up.

PLWH - People living with HIV, ART patient participants in RHICCA. Controls, or healthy controls, refer to HIV free study participants.

RHICCA - Reactivation of herpesviruses and inflammation as cardiovascular and cerebrovascular risk factors in antiretroviral initiators, in an African HIV population

3 Study objectives

The RHICCA study will test the hypothesis that immune activation, and in turn dysfunction, driven by HIV and reactivation of latent herpesvirus infections leads to increased CBD/CVD risk in adults aged > 35 years in SSA. We will address this through the following objectives;

  1. To determine if vasculopathy progression or occurrence of new-onset clinically significant vasculopathy is higher in adults aged > 35 years with HIV infection on ART compared to those without HIV

  2. To determine if vasculopathy progression or occurrence of new-onset clinically significant vasculopathy is higher in adults aged > 35 years with viral antigenaemia or chronic immune activation compared to those without viral antigenaemia or chronic immune activation. Specifically, we will determine if vasculopathy is higher:

    1. in PLWH with reactivated latent herpes viral infection, compared to those without reactivated latent herpes viral infection.
    2. in PLWH in the top 20% of markers for immune activation, immune senescence, inflammation or coagulation compared to the bottom 20%
    3. in PLWH with incomplete virological suppression or virological resurgence of HIV, compared to those with suppressed HIV plasma viral load

The secondary study objectives are to determine if viral antigenaemia or chronic immune activation increase occurrence of the following clinical events: 1) stroke, 2) myocardial infarction (MI), 3) angina (excluding MI), 4) peripheral vascular disease (PVD), 5) all-cause death/vascular-related death and 6) immune reconstitution vasculopathy.

4 Changes from the Statistical Analysis Plan

RHICCA is an observational study and much of the analysis is meant to be exploratory. As such, analyses differed in several ways from the SAP that was drafted. Major differences include:

  1. For objective 1, linear mixed models only are used to analyse associations with PWV.
  2. For objective 2b, the natural logarithm of ICAM-1, CD163 and IL-6 were used as predictors rather than categorising according to marker quintiles, which would have been statistically inefficient.
  3. Objective 2c was dropped as virtually all participants were virally suppressed.

5 Set-up

This section contains no output and serves as a container for several helper analysis functions as well as code to read-in and pre-process the data.

# this chunk has code for functions needed for downstream analyses

framinghamScore<-function(dat){
  # Based on equations in Appendix of D'Agostino et alk (2008) 10.1161/CIRCULATIONAHA.107.699579
  # Input 'dat' is a data frame with same column names as rhiccaDatWide in code much further below.
  # The column names will be renamed:
  #  crf.gender --> sex: "Male" or "Female"
  #  crf.age --> age: in years
  #  lims.HDL_Cholesterol_enrolment --> cholHDL = HDL cholesterol: in mmol/L (will be converted to mg/dL for model)
  #  lims.Cholesterol_enrolment --> cholTot = Total cholesterol: in mmol/L (will be converted to mg/dL for model)
  #  crf.bp_treat --> bp_treat = systolic blood pressure treatment: yes/no
  #  physio.bp_sys_enrolment --> bp_sys = systolic blood pressure: in mmHg
  #  crf.smoke --> smoker = smoking status: yes/no
  #  lims.Glucose_enrolment --> diabetes = diabetes status: yes/no (using RHICCA diabetes cut-off of 11.1 mmol/L)
  
  dat<-dat %>%
    dplyr::mutate(
      sex=crf.gender,
      age=crf.age,
      cholHDL=lims.HDL_Cholesterol_enrolment*38.67,
      cholTot=lims.Cholesterol_enrolment*38.67,
      bp_treat=ifelse(crf.bp_treat==1,"yes","no"),
      bp_sys=physio.bp_sys_enrolment,
      smoker=crf.smoke,
      diabetes=ifelse(lims.Glucose_enrolment>=11.1,"yes","no")
    ) %>%
    dplyr::mutate(
      framHamScore=1-case_when(
        sex=="Female" & bp_treat=="no"~0.95012^exp(2.32888*log(age)+1.20904*log(cholTot)-0.70833*log(cholHDL)+2.76157*log(bp_sys)+0.52873*ifelse(smoker=="yes",1,0)+0.69154*ifelse(diabetes=="yes",1,0)-26.1931),
        sex=="Female" & bp_treat=="yes"~0.95012^exp(0.95012^exp(2.32888*log(age)+1.20904*log(cholTot)-0.70833*log(cholHDL)+2.82263*log(bp_sys)+0.52873*ifelse(smoker=="yes",1,0)+0.69154*ifelse(diabetes=="yes",1,0)-26.1931)-26.1931),
        sex=="Male" & bp_treat=="no"~0.88936^exp(3.06117*log(age)+1.12370*log(cholTot)-0.93263*log(cholHDL)+1.93303*log(bp_sys)+0.65451*ifelse(smoker=="yes",1,0)+0.57367*ifelse(diabetes=="yes",1,0)-23.9802),
        sex=="Male" & bp_treat=="yes"~0.88936^exp(3.06117*log(age)+1.12370*log(cholTot)-0.93263*log(cholHDL)+1.99881*log(bp_sys)+0.65451*ifelse(smoker=="yes",1,0)+0.57367*ifelse(diabetes=="yes",1,0)-23.9802)
      )
    )
  
  return(dat$framHamScore)
}

6 Descriptive analyses

# create a big, long data frame combining constant, physiological, PWV, cIMT, ABPI, LIMS data
allPids<-unique(c(constDat$pid,
                  physioDatLong$pid,
                  pwvDatLong$pid,
                  cimtDatLong$pid,
                  abpiDatLong$pid,
                  limsDatLong$pid,
                  lumDatLong$pid))
allVisits<-c("enrolment",paste(sep="",seq(3,36,by=3),"months"),"unscheduled")

gr<-expand.grid(allPids,allVisits)

rhiccaDatLong<-data.frame(
  pid=gr[,1],
  visit=gr[,2]
)

rhiccaDatLong<-rhiccaDatLong %>%
  mutate(art=ifelse(visit=="enrolment",0,1))

addColPrefix<-function(dat,prefix,exclude=character(0),glue="."){
  colnames(dat)[!is.element(colnames(dat),set=exclude)]<-paste(sep=glue,prefix,colnames(dat)[!is.element(colnames(dat),set=exclude)])
  return(dat)
}

constDatTmp<-constDat %>%
  addColPrefix(prefix="crf",exclude=c("pid"))

cardioDatTmp<-cardioDat %>%
  addColPrefix(prefix="cardio",exclude=c("pid"))

physioDatLongTmp <- physioDatLong %>%
  dplyr::select(!c(ptype,physioTmpID)) %>%
  addColPrefix(prefix="physio",exclude=c("pid","timePoint"))

pwvDatLongTmp <- pwvDatLong %>%
  dplyr::select(!c(vtype,test_time,src,pwvTmpID,instanceid,project_dsid)) %>%
  addColPrefix(prefix="pwv",exclude=c("pid","timePoint"))

cimtDatLongTmp <- cimtDatLong %>%
  dplyr::select(!c(vtype,src,cimtTmpID,instanceid,project_dsid)) %>%
  addColPrefix(prefix="cimt",exclude=c("pid","timePoint"))

abpiDatLongTmp <- abpiDatLong %>%
  dplyr::select(!c(vtype,src,abpiTmpID,instanceid,project_dsid)) %>%
  addColPrefix(prefix="abpi",exclude=c("pid","timePoint"))

limsDatLongTmp <- limsDatLong %>%
  dplyr::select(!pid.x) %>%
  addColPrefix(prefix="lims",exclude=c("pid.y","timePoint"))

lumDatLongTmp <- lumDatLong %>%
  dplyr::select(!c(SampleID,timepoint)) %>%
  addColPrefix(prefix="lum",exclude=c("pid","timePoint"))

rhiccaDatLong<- rhiccaDatLong %>%
  left_join(y=constDatTmp,by="pid") %>%
  left_join(y=physioDatLongTmp,by=c("pid","visit"="timePoint")) %>%
  left_join(y=pwvDatLongTmp,by=c("pid","visit"="timePoint")) %>%
  left_join(y=cimtDatLongTmp,by=c("pid","visit"="timePoint")) %>%
  left_join(y=abpiDatLongTmp,by=c("pid","visit"="timePoint")) %>%
  left_join(y=limsDatLongTmp,by=c("pid"="pid.y","visit"="timePoint")) %>%
  left_join(y=lumDatLongTmp,by=c("pid","visit"="timePoint"))

rhiccaDatLong <- rhiccaDatLong %>%
  mutate(physio.bmi=physio.weight/(crf.height/100)^2,
         physio.waisthip=physio.waist/physio.hip,
         visitNum=ifelse(visit=="enrolment",0,as.integer(gsub(pattern="months",replacement="",visit))),
         visitNumExactPwv=(dmy(pwv.data_date)-dmy(crf.data_date))/dmonths(1),
         visitNumExactCimt=(dmy(cimt.data_date)-dmy(crf.data_date))/dmonths(1),
         visitNumExactAbpi=(dmy(abpi.data_date)-dmy(crf.data_date))/dmonths(1),
         visitNumExactPhysio=(dmy(physio.data_date)-dmy(crf.data_date))/dmonths(1)
  ) %>%
  mutate(physio.bmi_cat=case_when(physio.bmi<18.5~"underweight",
                                  physio.bmi>=18.5 & physio.bmi<25~"normal",
                                  physio.bmi>=25 & physio.bmi<30~"overweight",
                                  physio.bmi>=30~"obese"))

naCount<-rowSums(is.na(rhiccaDatLong))
idxRm<-which(naCount==ncol(rhiccaDatLong)-ncol(constDat))
if(length(idxRm)>0){rhiccaDatLong<-rhiccaDatLong[-idxRm,]}

egfrCalc<-function(creat_mumolPerL,sex,age,eth="black"){
  n<-length(creat_mumolPerL)
  if(n!=length(sex) | n!=length(age)){stop("creatMmolL, sex, age need to be vectors of the same length!")}
  
  # using thr 2021 CK-EPI eGFRcr(AS) equation from https://doi.org/110.1056/NEJMoa2102953
  # https://www.kidney.org/content/ckd-epi-creatinine-equation-2021
  creat_mgPerdl<-creat_mumolPerL*0.0113/ifelse(sex=="Female",0.7,0.9)
  res<-142 * (apply(X=cbind(creat_mgPerdl,rep(1,n)),FUN=min,MARGIN=1)^ifelse(sex=="Female",-0.241,-0.302)) * (apply(X=cbind(creat_mgPerdl,rep(1,n)),FUN=max,MARGIN=1)^(-1.200)) * (0.9938^age) * ifelse(sex=="Female",1.012,1) 
  
  # using the CKD-EPI equation from https://doi.org/10.7326/0003-4819-150-9-200905050-00006
  # const<-case_when(eth=="black" & sex=="Female"~166,eth=="black" & sex=="Male"~163,eth=="white" & sex=="Female"~144,eth=="white" & sex=="Male"~141)
  # 
  # creat<-creat_mumolPerL*0.0113
  # # creat<-creat_mumolPerL/11.312222
  # creat<-creat/ifelse(sex=="Female",0.7,0.9)
  # 
  # expo<-case_when(sex=="Female" & creat<=62~(-0.329),sex=="Female" & creat>62~(-1.209),sex=="Male" & creat<=80~(-0.411),sex=="Male" & creat>80~(-1.209))
  # 
  # res<-const*creat^expo*0.993^age
  # #res<-141 * (apply(X=cbind(creat,rep(1,n)),FUN=min,MARGIN=1)^ifelse(sex=="Female",-0.329,-0.411)) * (apply(X=cbind(creat,rep(1,n)),FUN=max,MARGIN=1)^(-1.209)) * (0.993^age) * ifelse(sex=="Female",1.018,1) * 1
  # # # # assuming everyone is black
  
  # using the 4-variable MDRD equations from https://doi.org/10.7326/0003-4819-145-4-200608150-00004
  #creat_mgPerdl<-reat_mumolPerL*0.0113
  #res<-175 * creat_mgPerdl^(-0.203) * age^(-0.203) * ifelse(eth=="black",1.212,1) * ifelse(sex=="Female",0.742,1) 
  return(res)
}

rhiccaDatLong <- rhiccaDatLong %>%
  mutate(eGFR=egfrCalc(creat_mumolPerL=lims.Creatinine,sex=crf.gender,age=crf.age))

rm(gr,naCount,idxRm,allPids,allVisits,constDatTmp,physioDatLongTmp,pwvDatLongTmp,cimtDatLongTmp,abpiDatLongTmp,limsDatLongTmp,lumDatLongTmp)

rhiccaDatLong<-rhiccaDatLong %>%
  filter(!(pid %in% pidsToRemove))

rhiccaDatWide <- rhiccaDatLong %>%
  filter(visit!="unscheduled") %>%
  pivot_wider(names_from=visit,values_from=!c(pid,starts_with("crf."),starts_with("cardio.")))

rhiccaDatWide <- rhiccaDatWide %>%
  mutate(
    iris=factor(case_when(
      pwv.pwv_enrolment>12 ~ "pre-existing vasculopathy",
      pwv.pwv_enrolment<=12 & pwv.pwv_6months<=12 ~ "no vasculopathy",
      pwv.pwv_enrolment<=12 & pwv.pwv_6months>12 ~ "new onset vasculopathy"
    ),levels=c("no vasculopathy","pre-existing vasculopathy","new onset vasculopathy")),
    ltfu_enrolment=ifelse(is.na(physio.data_date_enrolment) & is.na(physio.bmi_enrolment) & is.na(physio.temp_enrolment) & is.na(physio.hr_enrolment),1,0),
    ltfu_6months=ifelse(is.na(physio.data_date_6months) & is.na(physio.bmi_6months) & is.na(physio.temp_6months) & is.na(physio.hr_6months),1,0),
    ltfu_12months=ifelse(is.na(physio.data_date_12months) & is.na(physio.bmi_12months) & is.na(physio.temp_12months) & is.na(physio.hr_12months),1,0),
    ltfu_18months=ifelse(is.na(physio.data_date_18months) & is.na(physio.bmi_18months) & is.na(physio.temp_18months) & is.na(physio.hr_18months),1,0),
    ltfu_24months=ifelse(is.na(physio.data_date_24months) & is.na(physio.bmi_24months) & is.na(physio.temp_24months) & is.na(physio.hr_24months),1,0),
    ltfu_30months=ifelse(is.na(physio.data_date_30months) & is.na(physio.bmi_30months) & is.na(physio.temp_30months) & is.na(physio.hr_30months),1,0),
    ltfu_24months_reason=ltfuDat$reason[match(rhiccaDatWide$pid,ltfuDat$pid)],
    ltfu_24months_ineligDetails=ltfuDat$ineligibility_details[match(rhiccaDatWide$pid,ltfuDat$pid)]
  )

rhiccaDatLong<-rhiccaDatLong %>%
  add_column(iris=rhiccaDatWide$iris[match(rhiccaDatLong$pid,rhiccaDatWide$pid)],
             HIV_VL_base=rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)])

idsNoBase<-rhiccaDatLong %>%
  filter(is.na(crf.ptype)) %>%
  dplyr::select(pid) %>%
  unique()
idsNoBase<-setdiff(idsNoBase$pid,idsNoVL$pid)
write.csv(idsNoBase,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_noBaselineCrfData",gsub(pattern="-",replacement="",Sys.Date()),".csv"),row.names=F)

idxBMIunder<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bmi_cat_enrolment=="underweight"]))
idxBMInormal<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bmi_cat_enrolment=="normal"]))
idxBMIover<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bmi_cat_enrolment=="overweight"]))
idxBMIobese<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bmi_cat_enrolment=="obese"]))

idxHypertensionNormal<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bp_group_enrolment=="Normotensive"]))
idxHypertensionPre<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bp_group_enrolment=="Pre-hypertensive"]))
idxHypertensionHyper<-which(is.element(rhiccaDatLong$pid,set=rhiccaDatWide$pid[rhiccaDatWide$physio.bp_group_enrolment=="Hypertensive"]))

idxPriorART<-which(!is.na(rhiccaDatWide$crf.artnaive) & rhiccaDatWide$crf.artnaive=="prior ART" & rhiccaDatWide$crf.ptype=="Patient")
idxPriorARTNoVL<-which(!is.na(rhiccaDatWide$crf.artnaive) & rhiccaDatWide$crf.artnaive=="prior ART" & rhiccaDatWide$crf.ptype=="Patient" & !is.na(rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment) & rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment==150)
pidsPriorART<-rhiccaDatWide$pid[idxPriorART]
pidsPriorARTNoVL<-rhiccaDatWide$pid[idxPriorARTNoVL]

art<-data.frame(pid=rhiccaDatWide$pid,art=paste(sep=";",rhiccaDatWide$crf.artRegimen,rhiccaDatWide$crf.artRegimenNew))
art<-art[rhiccaDatWide$crf.ptype=="Patient",]
for(i in 1:nrow(art)){
  tmp<-unlist(strsplit(split=";",art$art[i]))
  tmp<-tmp[!grepl(tmp,pattern="NA")]
  tmp<-sort(unique(tmp))
  idx5A<-which(tmp=="5A")
  if(length(idx5A)==1){tmp<-c(tmp[idx5A],tmp[-idx5A])}
  tmp<-paste(collapse=", ",tmp)
  art$art[i]<-tmp
}
art<-art %>%
  mutate(
    artSimple=case_when(
    is.element(el=art,set=c("5A","5A, 13A"))~art,
    TRUE~"Other"),
    artSimple2Level=factor(case_when(
      grepl(pattern="13A",art)~"ART: Change to dolutegravir",
      TRUE~"ART: No change to dolutegravir"),levels=c("ART: Change to dolutegravir","ART: No change to dolutegravir"))
    )
    
tabArt<-as.data.frame(table(art$art))
tabArt<-tabArt[order(decreasing = T,tabArt$Freq),]

rhiccaDatWide$crf.artRegimen.full<-art$art[match(rhiccaDatWide$pid,art$pid)]
rhiccaDatWide$crf.artRegimen.simple<-art$artSimple[match(rhiccaDatWide$pid,art$pid)]
rhiccaDatWide$crf.artRegimen.2levels<-art$artSimple2Level[match(rhiccaDatWide$pid,art$pid)]

rhiccaDatWide$eGFR_existingCKD<-ifelse(!is.na(rhiccaDatWide$eGFR_enrolment) & rhiccaDatWide$eGFR_enrolment<60,"yes","no")

6.1 Data overview

6.1.1 Data completeness & loss-to-follow-up

After merging the different data tables, there are quite a few missing data points. Table 6.1 summarises the situation.

missSumFun<-function(dat){
  varVect<-c("pwv.pwv","cimt.cimt","abpi.abpi","lims.Cholesterol","lims.Glucose","eGFR","lum.CD163","lum.ICAM1","lum.IL6","lum.ILb")
  
  df<-data.frame(
    nTotal=nrow(dat),
    nBaseline=c(sum(dat$ltfu_enrolment==0),colSums(!is.na(dat[,c(paste(sep="_",varVect,"enrolment"))]))),
    n6months=c(sum(dat$ltfu_6months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect,"6months"))]))),
    n12months=c(sum(dat$ltfu_12months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect,"12months"))]))),
    n18months=c(sum(dat$ltfu_18months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect,"18months"))]))),
    n24months=c(sum(dat$ltfu_24months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect,"24months"))])))
  )
  
  varVect2<-c("lims.HIV_Abbott_Viral_Load_0pt2ml_P","lims.CD4_Absolute")
  dat<-dat[!is.na(dat$crf.ptype) & dat$crf.ptype=="Patient",]
  df2<-data.frame(
    nTotal=nrow(dat),
    nBaseline=c(sum(dat$ltfu_enrolment==0),colSums(!is.na(dat[,c(paste(sep="_",varVect2,"enrolment"))]))),
    n6months=c(sum(dat$ltfu_6months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect2,"6months"))]))),
    n12months=c(sum(dat$ltfu_12months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect2,"12months"))]))),
    n18months=c(sum(dat$ltfu_18months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect2,"18months"))]))),
    n24months=c(sum(dat$ltfu_24months==0),colSums(!is.na(dat[,c(paste(sep="_",varVect2,"24months"))])))
  )
  
  df<-rbind(df,df2)
  
  varNames<-c("Physiological data","PWV","CIMT","ABPI","Cholesterol","Glucose","eGFR","CD163","ICAM-1","IL-6","IL-1b","Physiological data (PLWH only)","HIV VL (PLWH only)","CD4+ (PLWH only)")
  rownames(df)<-varNames
  return(df)
}

datMiss<-missSumFun(rhiccaDatWide)
datMissNoMissCrf<-missSumFun(rhiccaDatWide %>% filter(!is.na(crf.ptype)))

datMiss %>%
  kable(caption="Numbers of non-missing data at the various visits for CRF, PWV, CIMT and ABPI.",col.names = c("Total","Baseline","6 month","12 months","18 months","24 months")) %>%
  kable_styling(full_width = F)
Table 6.1: Numbers of non-missing data at the various visits for CRF, PWV, CIMT and ABPI.
Total Baseline 6 month 12 months 18 months 24 months
Physiological data 923 903 791 765 726 676
PWV 923 904 779 754 720 675
CIMT 923 915 0 0 0 671
ABPI 923 911 784 759 726 682
Cholesterol 923 908 0 0 0 641
Glucose 923 909 0 0 0 679
eGFR 923 898 0 0 0 683
CD163 923 744 746 0 0 0
ICAM-1 923 746 745 0 0 0
IL-6 923 746 746 0 0 0
IL-1b 923 745 746 0 0 0
Physiological data (PLWH only) 713 713 611 584 559 520
HIV VL (PLWH only) 713 692 600 565 0 0
CD4+ (PLWH only) 713 703 603 579 0 528
missDatList<-list()
missDatList$pwv<-list()
missDatList$cimt<-list()
missDatList$abpi<-list()
missDatList$cholesterol<-list()
missDatList$triglycerides<-list()
missDatList$glucose<-list()
missDatList$VL<-list()

missDatList$pwv$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$pwv.pwv_enrolment)]
missDatList$pwv$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$pwv.pwv_24months)]

missDatList$cimt$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$cimt.cimt_enrolment)]
missDatList$cimt$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$cimt.cimt_24months)]

missDatList$abpi$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$abpi.abpi_enrolment)]
missDatList$abpi$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$abpi.abpi_24months)]

missDatList$cholesterol$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Cholesterol_enrolment)]
missDatList$cholesterol$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Cholesterol_24months)]

missDatList$triglycerides$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Triglycerides_enrolment)]
missDatList$triglycerides$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Triglycerides_24months)]

missDatList$glucose$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Glucose_enrolment)]
missDatList$glucose$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.Glucose_enrolment)]

missDatList$VL$baseline<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)]
missDatList$VL$fu24m<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$crf.ptype) & is.na(rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_24months)]

save(missDatList,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_allMerged_missingBaseline24monthData",gsub(pattern="-",replacement="",Sys.Date()),".RData"))
#####################
## clinical events ##
#####################

# confirm these!
clinEventsDat$PID[clinEventsDat$PID=="RE10930"]<-"RE1093O"
clinEventsDat$PID[clinEventsDat$PID=="RE12290"]<-"RE1229O"
#clinEventsDat$PID[clinEventsDat$PID=="RE1628A"]<-"RE1628V"
clinEventsDat$PID[clinEventsDat$PID=="RE14210"]<-"RE1421O"
clinEventsDat$PID[clinEventsDat$PID=="RE1118L"]<-"RE11181"
clinEventsDat$PID[clinEventsDat$PID=="RE1230I"]<-"RE12301"
clinEventsDat$PID[clinEventsDat$PID=="RE13281"]<-"RE1328I"
clinEventsDat$PID[clinEventsDat$PID=="RE1815H"]<-"RE1815P"

for(i in 1:nrow(clinEventsDat)){
  if(clinEventsDat$PID[i]==""){clinEventsDat$PID[i]<-clinEventsDat$PID[i-1]} # file is organised in this way that multiple events for the same participants do not repeat the PID but are in subsequent rows....
}

clinEventsDat$gender<-rhiccaDatWide$crf.gender[match(clinEventsDat$PID,rhiccaDatWide$pid)]
clinEventsDat$age_group<-rhiccaDatWide$crf.age_group[match(clinEventsDat$PID,rhiccaDatWide$pid)]
clinEventsDat$ptype<-rhiccaDatWide$crf.ptype[match(clinEventsDat$PID,rhiccaDatWide$pid)]
clinEventsDat$artnaive<-rhiccaDatWide$crf.artnaive[match(clinEventsDat$PID,rhiccaDatWide$pid)]

clinEventsDatFull<-clinEventsDat %>%
  mutate(degreeOfCertainty = gsub(pattern="^ ",replacement="",gsub(pattern=" $",replacement="",tolower(DEGREE.OF.CERTAINITY)))) %>%
  mutate(DIAGNOSIS = gsub(pattern="^ ",replacement="",gsub(pattern=" $",replacement="",tolower(DIAGNOSIS)))) %>%
  # mutate(diagnosisSimplified = case_when(
  #   grepl(DIAGNOSIS,pattern="death") ~ "death",
  #   grepl(DIAGNOSIS,pattern="anaemia") ~ "anaemia",
  #   grepl(DIAGNOSIS,pattern="tb$") ~ "tb",
  #   grepl(DIAGNOSIS,pattern="hypertension") ~ "hypertension",
  #   DIAGNOSIS=="herpes zoster, disseminated" ~ "disseminated herpes zoster",
  #   TRUE ~ DIAGNOSIS
  # )) %>%
  dplyr::select(!DEGREE.OF.CERTAINITY)

clinEventsDat<-clinEventsDatFull %>%
  filter(degreeOfCertainty!="not an event")

clinEventsDat$category<-case_when(
  grepl(clinEventsDat$DIAGNOSIS,pattern="aids-cancer")~"Cancer",
  grepl(clinEventsDat$DIAGNOSIS,pattern="anaemia")~"Systemic disease",
  grepl(clinEventsDat$DIAGNOSIS,pattern="candidiasis")~"Infection",
  grepl(clinEventsDat$DIAGNOSIS,pattern="renal")~"Systemic disease",
  grepl(clinEventsDat$DIAGNOSIS,pattern="hypertension")~"Systemic disease",
  grepl(clinEventsDat$DIAGNOSIS,pattern="liver")~"Systemic disease",
  grepl(clinEventsDat$DIAGNOSIS,pattern="hzv")~"Infection",
  grepl(clinEventsDat$DIAGNOSIS,pattern="tuberculosis")~"Infection",
  grepl(clinEventsDat$DIAGNOSIS,pattern="pneumonia")~"Infection",
  grepl(clinEventsDat$DIAGNOSIS,pattern="pneumocystis")~"Infection",
  grepl(clinEventsDat$DIAGNOSIS,pattern="salmonella")~"Infection",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_ERC_summary,pattern="Systemic")~"Systemic disease",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_ERC_summary,pattern="Cancer")~"Cancer",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_ERC_summary,pattern="Infections")~"Infection",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_ERC_summary,pattern="Cardiovascular")~"CVD",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_summary,pattern="Systemic")~"Systemic disease",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_summary,pattern="Cancer")~"Cancer",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_summary,pattern="Infections")~"Infection",
  clinEventsDat$DIAGNOSIS=="death" & grepl(clinEventsDat$Cause.of.death.1_summary,pattern="Cardiovascular")~"CVD",
  TRUE~"Undetermined"
)

#clinEventsDat$Category<-factor(clinEventsDat$Category)

#barPlotFun(dat=clinEventsDat,var="diagnosisSimplified",groupVar="ptype",labels=c("Control","ART patient"),xLab="Clinical events",legPos = "topleft",legDirHoriz = F)
rhiccaDatWide<-rhiccaDatWide %>%
  mutate(
    newOnsetDiabetes=case_when( # data dictionary does not list glucose lowering medication variable??
      lims.Glucose_enrolment>=11.1~"pre-existing diabetes",
      lims.Glucose_enrolment<11.1 & lims.Glucose_24months>=11.1~"new diabetes",
      is.na(lims.Glucose_enrolment) | is.na(lims.Glucose_24months)~NA_character_,
      TRUE~"no diabetes"
    ),
    newOnsetHypercholesterolemia=case_when(
      lims.Cholesterol_enrolment>=5.2~"pre-existing hypercholesterolemia",
      lims.Cholesterol_enrolment<5.2 & lims.Cholesterol_24months>=5.2~"new hypercholesterolemia",
      is.na(lims.Cholesterol_enrolment) | is.na(lims.Cholesterol_24months)~NA_character_,
      TRUE~"no hypercholesterolemia"
    ),
    newOnsetKidneyCondition=case_when(
      eGFR_enrolment<60~"pre-existing kidney condition",
      #eGFR_enrolment<60 & eGFR_6months>=60~"new kidney condition",
      eGFR_enrolment>=60 & eGFR_24months<60~"new kidney condition",
      #is.na(eGFR_enrolment)~NA_character_,
      is.na(eGFR_enrolment) | is.na(eGFR_24months)~NA_character_,
      #is.na(eGFR_6months) & is.na(eGFR_24months)~NA_character_,
      #is.na(eGFR_6months) & (eGFR_enrolment<60 & eGFR_24months<60)~NA_character_,
      #is.na(eGFR_24months) & (eGFR_enrolment<60 & eGFR_6months<60)~NA_character_,
      TRUE~"no kidney condition"
    ),
    newOnsetABPI=case_when(
      abpi.abpi_enrolment<=0.9~"pre-existing ABPI vasculopathy",
      abpi.abpi_enrolment>0.9 & abpi.abpi_24months<=0.9~"new ABPI vasculopathy",
      is.na(abpi.abpi_enrolment) | is.na(abpi.abpi_24months)~NA_character_,
      TRUE~"no ABPI vasculopathy"
    ),
    newOnsetPWV=case_when(
      pwv.pwv_enrolment>12~"pre-existing PWV vasculopathy",
      pwv.pwv_enrolment<=12 & pwv.pwv_24months>12~"new PWV vasculopathy",
      is.na(pwv.pwv_enrolment) | is.na(pwv.pwv_24months)~NA_character_,
      TRUE~"no PWV vasculopathy"
    ),
    newOnsetCIMT=case_when(
      cimt.cimt_enrolment>0.78~"pre-existing CIMT vasculopathy",
      cimt.cimt_enrolment<=0.78 & cimt.cimt_24months>0.78~"new CIMT vasculopathy",
      is.na(cimt.cimt_enrolment) | is.na(cimt.cimt_24months)~NA_character_,
      TRUE~"no PWV vasculopathy"
    ),
    newOnsetCIMT0.9=case_when(
      cimt.cimt_enrolment>0.9~"pre-existing CIMT vasculopathy",
      cimt.cimt_enrolment<=0.9 & cimt.cimt_24months>0.9~"new CIMT vasculopathy",
      is.na(cimt.cimt_enrolment) | is.na(cimt.cimt_24months)~NA_character_,
      TRUE~"no PWV vasculopathy"
    ),
    newOnsetMyocardialInfarction=case_when(
      pid %in% cardioDat$pid[cardioDat$mc_mi==1 & cardioDat$timeSinceBaseline<30]~"pre-existing MI",
      pid %in% cardioDat$pid[cardioDat$mc_mi==1 & cardioDat$timeSinceBaseline>=30]~"new MI",
      pid %in% cardioDat$pid[is.na(cardioDat$timeSinceBaseline)]~NA_character_,
      TRUE~"noMI"
    )
  )

rhiccaDatWide<-rhiccaDatWide %>%
  mutate(
    newOnsetClinEvent=case_when(
      newOnsetDiabetes=="new diabetes"~1,
      newOnsetHypercholesterolemia=="new hypercholesterolemia"~1,
      newOnsetKidneyCondition=="new kidney condition"~1,
      newOnsetABPI=="new ABPI vasculopathy"~1,
      newOnsetPWV=="new PWV vasculopathy"~1,
      newOnsetCIMT=="new CIMT vasculopathy"~1,
      newOnsetMyocardialInfarction=="new MI"~1,
      TRUE~0
    ),
    newOnsetClinEventNoAbpiPwvCimt=case_when(
      newOnsetDiabetes=="new diabetes"~1,
      newOnsetHypercholesterolemia=="new hypercholesterolemia"~1,
      newOnsetKidneyCondition=="new kidney condition"~1,
      newOnsetMyocardialInfarction=="new MI"~1,
      TRUE~0
    )
  )
    
rhiccaDatWide<-rhiccaDatWide %>%
  mutate(
    clinEvent=case_when(
      newOnsetClinEvent==1~1,
      pid %in% clinEventsDat$PID~1,
      TRUE~0
    ),
    clinEventConfirmed=case_when(
      newOnsetClinEventNoAbpiPwvCimt==1~1,
      pid %in% clinEventsDat$PID[clinEventsDat$degreeOfCertainty=="confirmed"]~1,
      TRUE~0
    )
  )

trblShoot<-data.frame(
  clinicalEvent=c("Diabetes","Hypercholesterolemia","Chronic_kidney_disease","Vasculopathy (ABPI)","Vasculopathy (PWV)","Vasculopathy (CIMT)","MI"),
  variable=c("lims.Glucose","lims.Cholesterol","eGFR","ABPI","PWV","CIMT","MI"),
  nTotal=nrow(rhiccaDatWide),
  missingNewOnsetStatus=c(
    sum(is.na(rhiccaDatWide$newOnsetDiabetes)),
    sum(is.na(rhiccaDatWide$newOnsetHypercholesterolemia)),
    sum(is.na(rhiccaDatWide$newOnsetKidneyCondition)),
    sum(is.na(rhiccaDatWide$newOnsetABPI)),
    sum(is.na(rhiccaDatWide$newOnsetPWV)),
    sum(is.na(rhiccaDatWide$newOnsetCIMT)),
    sum(is.na(rhiccaDatWide$newOnsetMyocardialInfarction))
  ),
  missingVarBaseline=c(
    sum(is.na(rhiccaDatWide$lims.Glucose_enrolment)),
    sum(is.na(rhiccaDatWide$lims.Cholesterol_enrolment)),
    sum(is.na(rhiccaDatWide$eGFR_enrolment)),
    sum(is.na(rhiccaDatWide$abpi.abpi_enrolment)),
    sum(is.na(rhiccaDatWide$pwv.pwv_enrolment)),
    sum(is.na(rhiccaDatWide$cimt.cimt_enrolment)),
    NA
  ),
  missingVar6months=c(
    sum(is.na(rhiccaDatWide$lims.Glucose_6months)),
    sum(is.na(rhiccaDatWide$lims.Cholesterol_6months)),
    sum(is.na(rhiccaDatWide$eGFR_6months)),
    sum(is.na(rhiccaDatWide$abpi.abpi_6months)),
    sum(is.na(rhiccaDatWide$pwv.pwv_6months)),
    sum(is.na(rhiccaDatWide$cimt.cimt_6months)),
    NA
  ),
  missingVar24months=c(
    sum(is.na(rhiccaDatWide$lims.Glucose_24months)),
    sum(is.na(rhiccaDatWide$lims.Cholesterol_24months)),
    sum(is.na(rhiccaDatWide$eGFR_24months)),
    sum(is.na(rhiccaDatWide$abpi.abpi_24months)),
    sum(is.na(rhiccaDatWide$pwv.pwv_24months)),
    sum(is.na(rhiccaDatWide$cimt.cimt_24months)),
    NA
  )
)

write.csv(trblShoot,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_missingNewOnsetClinicalEvents_",gsub(pattern="-",replacement="",Sys.Date()),".csv"),row.names=F)

rhiccaDatWide<-rhiccaDatWide %>% 
  add_column(clinEventCategory=character(nrow(rhiccaDatWide))) %>%
  add_column(clinEventCategoryConfirmed=character(nrow(rhiccaDatWide))) %>%
  add_column(clinEventCategoryConfirmedSystemicType=character(nrow(rhiccaDatWide)))

rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"],"Systemic disease")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"],"Systemic disease")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"],"Systemic disease")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetABPI) & rhiccaDatWide$newOnsetABPI=="new ABPI vasculopathy"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetABPI) & rhiccaDatWide$newOnsetABPI=="new ABPI vasculopathy"],"CVD")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetPWV) & rhiccaDatWide$newOnsetPWV=="new PWV vasculopathy"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetPWV) & rhiccaDatWide$newOnsetPWV=="new PWV vasculopathy"],"CVD")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy"],"CVD")
rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetMyocardialInfarction) & rhiccaDatWide$newOnsetMyocardialInfarction=="new MI"]<-paste(sep=";",rhiccaDatWide$clinEventCategory[!is.na(rhiccaDatWide$newOnsetMyocardialInfarction) & rhiccaDatWide$newOnsetMyocardialInfarction=="new MI"],"CVD")

rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"],"Systemic disease")
rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetDiabetes) & rhiccaDatWide$newOnsetDiabetes=="new diabetes"],"diabetes")
rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"],"Systemic disease")
rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetHypercholesterolemia) & rhiccaDatWide$newOnsetHypercholesterolemia=="new hypercholesterolemia"],"hypercholesterolemia")
rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"],"Systemic disease")
rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmedSystemicType[!is.na(rhiccaDatWide$newOnsetKidneyCondition) & rhiccaDatWide$newOnsetKidneyCondition=="new kidney condition"],"kidney disease")
rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetMyocardialInfarction) & rhiccaDatWide$newOnsetMyocardialInfarction=="new MI"]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmed[!is.na(rhiccaDatWide$newOnsetMyocardialInfarction) & rhiccaDatWide$newOnsetMyocardialInfarction=="new MI"],"CVD")

for(j in 1:nrow(clinEventsDat)){
  pid<-clinEventsDat$PID[j]
  rhiccaDatWide$clinEventCategory[rhiccaDatWide$pid==pid]<-paste(sep=";",rhiccaDatWide$clinEventCategory[rhiccaDatWide$pid==pid],clinEventsDat$category[j])
  if(clinEventsDat$degreeOfCertainty[j]=="confirmed"){
    rhiccaDatWide$clinEventCategoryConfirmed[rhiccaDatWide$pid==pid]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmed[rhiccaDatWide$pid==pid],clinEventsDat$category[j])
    if(clinEventsDat$category[j]=="Systemic disease"){
      rhiccaDatWide$clinEventCategoryConfirmedSystemicType[rhiccaDatWide$pid==pid]<-paste(sep=";",rhiccaDatWide$clinEventCategoryConfirmedSystemicType[rhiccaDatWide$pid==pid],clinEventsDat$DIAGNOSIS[j])
    }
  }
}

rhiccaDatWide$clinEventCategory<-gsub(rhiccaDatWide$clinEventCategory,pattern="^;",replacement="")
rhiccaDatWide$clinEventCategoryConfirmed<-gsub(rhiccaDatWide$clinEventCategoryConfirmed,pattern="^;",replacement="")
rhiccaDatWide$clinEventCategoryConfirmedSystemicType<-gsub(rhiccaDatWide$clinEventCategoryConfirmedSystemicType,pattern="^;",replacement="")
rhiccaDatWide<-rhiccaDatWide %>%
  mutate(
    numClinEventsPerParticipant=0,
    numClinEventsPerParticipantNoOnset=0,
    numClinEventsPerParticipantNoPwvCimtAbpi=0,
    numClinEventsPerParticipantCVD=0,
    numClinEventsPerParticipantCVDNoOnset=0,
    numClinEventsPerParticipantInfection=0,
    numClinEventsPerParticipantSystemic=0,
    numClinEventsConfirmedPerParticipant=0,
    numClinEventsConfirmedPerParticipantWithDerivedWithoutPwvCimtAbpi=0,
    numClinEventsConfirmedPerParticipantCVD=0,
    numClinEventsConfirmedPerParticipantInfection=0,
    numClinEventsConfirmedPerParticipantSystemic=0,
    numClinEventsPwvCimtAbpi=0,
    numClinEventsPwvCimt=0,
    numClinEventsCimt=0
  )

idx<-which(rhiccaDatWide$clinEvent==1)

for(i in idx){
  rhiccaDatWide$numClinEventsPerParticipant[i]<-rhiccaDatWide$numClinEventsPerParticipant[i]+length(unlist(strsplit(split=";",rhiccaDatWide$clinEventCategory[i])))
  rhiccaDatWide$numClinEventsPerParticipantCVD[i]<-rhiccaDatWide$numClinEventsPerParticipantCVD[i]+sum(grepl(pattern="CVD",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategory[i]))))
  rhiccaDatWide$numClinEventsPerParticipantInfection[i]<-rhiccaDatWide$numClinEventsPerParticipantInfection[i]+sum(grepl(pattern="Infection",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategory[i]))))
  rhiccaDatWide$numClinEventsPerParticipantSystemic[i]<-rhiccaDatWide$numClinEventsPerParticipantSystemic[i]+sum(grepl(pattern="Systemic",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategory[i]))))
  
  rhiccaDatWide$numClinEventsPerParticipantNoOnset[i]<-rhiccaDatWide$numClinEventsPerParticipant[i]-ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetPWV[i]) & rhiccaDatWide$newOnsetPWV[i]=="new PWV vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetABPI[i]) & rhiccaDatWide$newOnsetABPI[i]=="new ABPI vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetDiabetes[i]) & rhiccaDatWide$newOnsetDiabetes[i]=="new diabetes",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetHypercholesterolemia[i]) & rhiccaDatWide$newOnsetHypercholesterolemia[i]=="new hypercholesterolemia",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetKidneyCondition[i]) & rhiccaDatWide$newOnsetKidneyCondition[i]=="new kidney condition",1,0)
  
  rhiccaDatWide$numClinEventsPerParticipantNoPwvCimtAbpi[i]<-rhiccaDatWide$numClinEventsPerParticipant[i]-ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetPWV[i]) & rhiccaDatWide$newOnsetPWV[i]=="new PWV vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetABPI[i]) & rhiccaDatWide$newOnsetABPI[i]=="new ABPI vasculopathy",1,0)
  
  rhiccaDatWide$numClinEventsPerParticipantCVDNoOnset[i]<-rhiccaDatWide$numClinEventsPerParticipantCVD[i]-ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetPWV[i]) & rhiccaDatWide$newOnsetPWV[i]=="new PWV vasculopathy",1,0)-ifelse(!is.na(rhiccaDatWide$newOnsetABPI[i]) & rhiccaDatWide$newOnsetABPI[i]=="new ABPI vasculopathy",1,0)
  
  rhiccaDatWide$numClinEventsPwvCimtAbpi[i]<-ifelse(!is.na(rhiccaDatWide$newOnsetPWV[i]) & rhiccaDatWide$newOnsetPWV[i]=="new PWV vasculopathy",1,0)+ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)+ifelse(!is.na(rhiccaDatWide$newOnsetABPI[i]) & rhiccaDatWide$newOnsetABPI[i]=="new ABPI vasculopathy",1,0)
  
  rhiccaDatWide$numClinEventsPwvCimt[i]<-ifelse(!is.na(rhiccaDatWide$newOnsetPWV[i]) & rhiccaDatWide$newOnsetPWV[i]=="new PWV vasculopathy",1,0)+ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)
  
  rhiccaDatWide$numClinEventsCimt[i]<-ifelse(!is.na(rhiccaDatWide$newOnsetCIMT[i]) & rhiccaDatWide$newOnsetCIMT[i]=="new CIMT vasculopathy",1,0)
  
  if(i %in% which(rhiccaDatWide$clinEventConfirmed==1)){
    rhiccaDatWide$numClinEventsConfirmedPerParticipant[i]<-rhiccaDatWide$numClinEventsConfirmedPerParticipant[i]+length(unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[i])))
    rhiccaDatWide$numClinEventsConfirmedPerParticipantWithDerivedWithoutPwvCimtAbpi[i]<-rhiccaDatWide$numClinEventsConfirmedPerParticipant[i]+length(unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[i])))+ifelse(!is.na(rhiccaDatWide$newOnsetDiabetes[i]) & rhiccaDatWide$newOnsetDiabetes[i]=="new diabetes",1,0)+ifelse(!is.na(rhiccaDatWide$newOnsetHypercholesterolemia[i]) & rhiccaDatWide$newOnsetHypercholesterolemia[i]=="new hypercholesterolemia",1,0)+ifelse(!is.na(rhiccaDatWide$newOnsetKidneyCondition[i]) & rhiccaDatWide$newOnsetKidneyCondition[i]=="new kidney condition",1,0)
    rhiccaDatWide$numClinEventsConfirmedPerParticipantCVD[i]<-rhiccaDatWide$numClinEventsConfirmedPerParticipantCVD[i]+sum(grepl(pattern="CVD",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[i]))))
    rhiccaDatWide$numClinEventsConfirmedPerParticipantInfection[i]<-rhiccaDatWide$numClinEventsConfirmedPerParticipantInfection[i]+sum(grepl(pattern="Infection",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[i]))))
    rhiccaDatWide$numClinEventsConfirmedPerParticipantSystemic[i]<-rhiccaDatWide$numClinEventsConfirmedPerParticipantSystemic[i]+sum(grepl(pattern="Systemic",unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[i]))))
  }
}

rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT<-rhiccaDatWide$numClinEventsConfirmedPerParticipantCVD+ifelse(grepl(pattern="new",rhiccaDatWide$newOnsetCIMT),1,0)
rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMTPWV<-rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT+ifelse(grepl(pattern="new",rhiccaDatWide$newOnsetPWV),1,0)
tmpDatAll <- rhiccaDatLong %>%
  dplyr::select(pid,crf.ptype,visit,pwv.pwv,cimt.cimt,abpi.abpi,eGFR,lims.CD4_Absolute) %>%
  filter(!is.na(crf.ptype) & is.element(visit,set=c("enrolment","6months","12months","18months","24months","30months","36months"))) %>%
  group_by(visit,crf.ptype) %>%
  summarise(pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
            cimtMean=mean(cimt.cimt,na.rm=T),cimtSE=sd(cimt.cimt,na.rm=T)/sqrt(sum(!is.na(cimt.cimt))),
            abpiMean=mean(abpi.abpi,na.rm=T),abpiSE=sd(abpi.abpi,na.rm=T)/sqrt(sum(!is.na(abpi.abpi))),
            egfrMean=mean(eGFR,na.rm=T),egfrSE=sd(eGFR,na.rm=T)/sqrt(sum(!is.na(eGFR))),
            cd4Mean=mean(lims.CD4_Absolute,na.rm=T),cd4SE=sd(lims.CD4_Absolute,na.rm=T)/sqrt(sum(!is.na(lims.CD4_Absolute))),
            .groups="drop") %>%
  filter(visit!="unscheduled") %>%
  mutate(visitNum=ifelse(visit=="enrolment",0,as.integer(gsub(pattern="months",replacement="",visit))))
kableRn<-function(.data,row_names=NULL, ...){
  if(!is.null(row_names)){
    datTmp<-.data
    row.names(datTmp)<-row_names
    res<-kable(datTmp, row.names=T, ...)
  }else{
    res<-kable(.data, ...)
  }
  
  return(res)
}
idx<-which(!is.na(rhiccaDatWide$lims.Cholesterol_enrolment) & rhiccaDatWide$lims.Cholesterol_enrolment>=1000)
datTmp<-rhiccaDatWide[idx,]

rhiccaDatWide$lims.Cholesterol_enrolment[idx]<-NA

6.1.2 Loss to follow-up

The loss-to-follow-up rates over time are visualised on Figure 6.1.

binomCI<-function(x,n,type="low"){
  if(length(x)!=length(n)){stop("x and n need to be of same length!")}
  res<-rep(NA,length(x))
  
  for(i in 1:length(x)){
    if(type=="low"){
      res[i]<-binom.test(x=x[i],n=n[i])$conf.int[1]
    }else if(type=="high"){
      res[i]<-binom.test(x=x[i],n=n[i])$conf.int[2]
    }
  }
  
  return(res)
}

datTmp<-rhiccaDatWide %>%
  filter(ltfu_enrolment==0) %>%
  group_by(crf.ptype) %>%
  summarise(
    n=n(),
    n00=sum(ltfu_enrolment==1),
    n06=sum(ltfu_6months==1),
    n12=sum(ltfu_12months==1),
    n18=sum(ltfu_18months==1),
    n24=sum(ltfu_24months==1),
    .groups="drop"
  ) %>%
  pivot_longer(cols=c(n00,n06,n12,n18,n24),names_to="visit",values_to="k") %>%
  mutate(
    month=case_when(
      visit=="n00"~0,
      visit=="n06"~6,
      visit=="n12"~12,
      visit=="n18"~18,
      visit=="n24"~24
    ),
    prop=k/n,
    propLow=binomCI(x=k,n=n,type="low"),
    propHigh=binomCI(x=k,n=n,type="high")
  )

g<-datTmp %>%
  ggplot(mapping=aes(x=month,y=prop,ymin=propLow,ymax=propHigh,col=crf.ptype,fill=crf.ptype)) +
  geom_point(size=2) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("Loss-to-follow-up (LTFU) rates over time per participant type.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("LTFU proportion") 

print(g)
LTFU rates over time.

Figure 6.1: LTFU rates over time.

We can also tabulate the reasons for LTFU in Table 6.2.

datTmp<-rhiccaDatWide %>%
  filter(ltfu_enrolment==0) %>%
  group_by(crf.ptype) %>%
  summarise(
    n=n(),
    n24=sum(ltfu_24months==1),
    n24_death=sum(ltfu_24months==1 & ltfu_24months_reason=="DEATH",na.rm=T),
    n24_move=sum(ltfu_24months==1 & ltfu_24months_reason=="MIGRATED",na.rm=T),
    n24_consent=sum(ltfu_24months==1 & ltfu_24months_reason=="CONSENT WITHTDRAW",na.rm=T),
    n24_ineligible=sum(ltfu_24months==1 & ltfu_24months_reason=="RETROSPECTIVE DISCOVERY OF STUDY INELIGIBILITY",na.rm=T),
    n24_otherAlive=sum(ltfu_24months==1 & ltfu_24months_reason=="ALIVE",na.rm=T),
    n24_unknown=sum(ltfu_24months==1 & is.na(ltfu_24months_reason)),
    .groups="drop"
  )

cnames<-datTmp$crf.ptype
datTmp<-as.data.frame(t(datTmp[,-1]))
colnames(datTmp)<-cnames
rownames(datTmp)<-c("Total number of participants","Lost to follow-up","Dead","Moved away","Withdrew consent","Ineligible","Other reason but still alive","Unknown")

datTmp$ControlProp<-round(digits=3,100*datTmp$Control/datTmp$Control[1])
datTmp$PatientProp<-round(digits=3,100*datTmp$Patient/datTmp$Patient[1])

datTmp$Control<-paste(sep="",datTmp$Control," (",format(nsmall=2,datTmp$ControlProp),"%)")
datTmp$Patient<-paste(sep="",datTmp$Patient," (",format(nsmall=2,datTmp$PatientProp),"%)")

datTmp %>%
  dplyr::select(Control,Patient) %>%
  kable(caption="Reasons for loss-to-follow-up at 24 months by participant type.",align = "l") %>%
  kable_styling(full_width = F)
Table 6.2: Reasons for loss-to-follow-up at 24 months by participant type.
Control Patient
Total number of participants 190 (100.000%) 713 (100.000%)
Lost to follow-up 39 ( 20.526%) 193 ( 27.069%)
Dead 0 ( 0.000%) 37 ( 5.189%)
Moved away 7 ( 3.684%) 44 ( 6.171%)
Withdrew consent 4 ( 2.105%) 17 ( 2.384%)
Ineligible 4 ( 2.105%) 3 ( 0.421%)
Other reason but still alive 24 ( 12.632%) 86 ( 12.062%)
Unknown 0 ( 0.000%) 6 ( 0.842%)
datTmp<-rhiccaDatWide %>%
  filter(ltfu_enrolment==0 & ltfu_24months==1 & ltfu_24months_reason=="RETROSPECTIVE DISCOVERY OF STUDY INELIGIBILITY")

table(datTmp$crf.ptype,datTmp$ltfu_24months_ineligDetails) %>%
  t() %>%
  kable(caption="Reasons for retrospective ineligibility (participants with baseline CRF data only).") %>%
  kable_styling(full_width = F)
Table 6.2: Reasons for retrospective ineligibility (participants with baseline CRF data only).
Control Patient
NOT ART NAIIVE 0 3
PRE-EXISTING HEART FAILURE 1 0
SERO-CONVERSION 3 0
# removing participants without baseline CRF data
pidsNoCrf<-rhiccaDatWide$pid[rhiccaDatWide$ltfu_enrolment==1]
rhiccaDatWide<-rhiccaDatWide %>% filter(! pid %in% pidsNoCrf)
rhiccaDatLong<-rhiccaDatLong %>% filter(! pid %in% pidsNoCrf)

# Removing the ineligibles
pidsIneligible<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$ltfu_24months_reason) & rhiccaDatWide$ltfu_24months_reason=="RETROSPECTIVE DISCOVERY OF STUDY INELIGIBILITY"]
rhiccaDatWide<-rhiccaDatWide %>% filter(! pid %in% pidsIneligible)
rhiccaDatLong<-rhiccaDatLong %>% filter(! pid %in% pidsIneligible)

# cleaning redundant columns
sumNA<-colSums(is.na(rhiccaDatWide))
rhiccaDatWide<-rhiccaDatWide[,sumNA<nrow(rhiccaDatWide)]

obsTime<-rhiccaDatLong %>%
  dplyr::select(c(pid,crf.gender,crf.ptype,crf.age_group,contains("_date"))) %>%
  mutate(
    crf.data_date=dmy(crf.data_date),
    physio.data_date=dmy(physio.data_date),
    pwv.data_date=dmy(pwv.data_date),
    cimt.data_date=dmy(cimt.data_date),
    abpi.data_date=dmy(abpi.data_date),
    lims.data_date=as_date(mdy_hms(gsub(lims.sample_date,pattern="\\:000[AP]M",replacement="")))
  ) %>%
  mutate(
    lims.data_date=as_date(case_when(
      grepl(as.character(lims.data_date),pattern="2014")~NA_character_,
      TRUE~as.character(lims.data_date)
    ))
  ) %>%
  dplyr::select(!contains("sample")) %>%
  pivot_longer(cols=contains("_date"),names_to="type",values_to="date") %>%
  group_by(pid) %>%
  summarise(
    crf.gender=paste(collapse="_",unique(crf.gender)),
    crf.ptype=paste(collapse="_",unique(crf.ptype)),
    crf.age_group=paste(collapse="_",unique(crf.age_group)),
    recruitDate=min(date,na.rm=TRUE),
    lastVisitDate=max(date,na.rm=TRUE)
  ) %>%
  mutate(
    obsTime=ymd(lastVisitDate)-ymd(recruitDate)
  )

rhiccaDatWide<-rhiccaDatWide %>%
  mutate(
    recruitDate=as.character(obsTime$recruitDate[match(pid,obsTime$pid)]),
    lastVisitDate=as.character(obsTime$lastVisitDate[match(pid,obsTime$pid)]),
    obsTime=obsTime$obsTime[match(pid,obsTime$pid)]
    )
cmvvzvDat<-read.csv(cmvvzvFile)

# chat with Laura on 20/07/2022
# 1. For VZV ignore the confirmation results
# 2. For CMV, use the "CMV IgG Result" measurements unless these are ">250.0" in which case use the "CMV IgG Dilution" measurements
# Try if the missing Subject IDs can be inferred from the lab IDs ("Subject.ID.1")

cmvvzvDat$Subject.ID[cmvvzvDat$Subject.ID=="RE16903"]<-"RE1690J" # Laura indicated to correct this, but there aren't any instances where this applies
cmvvzvDat$Subject.ID[cmvvzvDat$Subject.ID=="RE1112B"]<-"RE1121B" # Laura indicated to correct this, but there aren't any instances where this applies
cmvvzvDat$Subject.ID[cmvvzvDat$Subject.ID=="RE1632Z"]<-"RE16322"
cmvvzvDat$Subject.ID[cmvvzvDat$Subject.ID=="RE1028S"]<-"RE10285"

cmvDat<-cmvvzvDat %>%
  dplyr::filter(Test=="CMV IgG Result")

cmvDilDat<-cmvvzvDat %>%
  dplyr::filter(Test=="CMV IgG Dilution")

vzvDat<-cmvvzvDat %>%
  dplyr::filter(Test=="Varizell Zoster IgG") 

for(j in 1:nrow(cmvDat)){
  if(cmvDat$Result[j]==">250.0"){
    #print(c(j,cmvDat$Subject.ID[j],cmvDat$Result[j],cmvDilDat$Result[cmvDilDat$labno==cmvDat$labno[j]]))
    if(length(cmvDilDat$Result[cmvDilDat$labno==cmvDat$labno[j]])!=0){
      cmvDat$Result[j]<-cmvDilDat$Result[cmvDilDat$labno==cmvDat$labno[j]]
    }
  }
}

idx2remove<-integer(0)
for(j in which(cmvDat$Subject.ID %in% c(".","RE"))){
  pid<-limsDatMerged$pid.x[limsDatMerged$lab_id==cmvDat$Subject.ID.1[j]]
  if(length(pid)==1){cmvDat$Subject.ID[j]<-pid}else{idx2remove<-c(idx2remove,j)}
}
if(length(idx2remove)>0){cmvDat<-cmvDat[-idx2remove,]}

idx2remove<-integer(0)
for(j in which(vzvDat$Subject.ID %in% c(".","RE"))){
  pid<-limsDatMerged$pid.x[limsDatMerged$lab_id==vzvDat$Subject.ID.1[j]]
  if(length(pid)==1){vzvDat$Subject.ID[j]<-pid}else{idx2remove<-c(idx2remove,j)}
}
if(length(idx2remove)>0){vzvDat<-vzvDat[-idx2remove,]}

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD10Q" & cmvDat$Subject.ID=="RE1869Y"]<-"CBD1Q0"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD10Q" & vzvDat$Subject.ID=="RE1869Y"]<-"CBD1Q0"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD114" & cmvDat$Subject.ID=="RE1539X"]<-"CBD1I4"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD114" & vzvDat$Subject.ID=="RE1539X"]<-"CBD1I4"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD115" & cmvDat$Subject.ID=="RE1540A"]<-"CBD1I5"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD115" & vzvDat$Subject.ID=="RE1540A"]<-"CBD1I5"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD11F" & cmvDat$Subject.ID=="RE15506"]<-"CBD1IF"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD11F" & vzvDat$Subject.ID=="RE15506"]<-"CBD1IF"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD11H" & cmvDat$Subject.ID=="RE1158M"]<-"CBD1IH"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1IH" & cmvDat$Subject.ID=="RE1158M"]<-"RE15522"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD11H" & vzvDat$Subject.ID=="RE1158M"]<-"CBD1IH"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1IH" & vzvDat$Subject.ID=="RE1158M"]<-"RE15522"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD11V" & cmvDat$Subject.ID=="RE15657"]<-"CBD1IV"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1IV" & cmvDat$Subject.ID=="RE15657"]<-"RE1565T"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD11V" & vzvDat$Subject.ID=="RE15657"]<-"CBD1IV"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1IV" & vzvDat$Subject.ID=="RE15657"]<-"RE1565T"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD11W" & cmvDat$Subject.ID=="RE1566R"]<-"CBD1IW"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD11W" & vzvDat$Subject.ID=="RE1566R"]<-"CBD1IW"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD12I" & cmvDat$Subject.ID=="RE1354E"]<-"CBE12I"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD12I" & vzvDat$Subject.ID=="RE1354E"]<-"CBE12I"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD12Y" & cmvDat$Subject.ID=="RE13754"]<-"CBE12Y"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD12Y" & vzvDat$Subject.ID=="RE13754"]<-"CBE12Y"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD14S" & cmvDat$Subject.ID=="RE15657"]<-"CBF14S"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD14S" & cmvDat$Subject.ID=="RE1044Y"]<-"RE1144Y"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD14S" & vzvDat$Subject.ID=="RE15657"]<-"CBF14S"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD14S" & vzvDat$Subject.ID=="RE1044Y"]<-"RE1144Y"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD17B" & cmvDat$Subject.ID=="RE1162N"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD17B" & vzvDat$Subject.ID=="RE1162N"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD188" & cmvDat$Subject.ID=="RE12610"]<-"CBF18B"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD18B" & cmvDat$Subject.ID=="RE12610"]<-"RE1261O"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD188" & vzvDat$Subject.ID=="RE12610"]<-"CBF18B"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD18B" & vzvDat$Subject.ID=="RE12610"]<-"RE1261O"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD18X" & cmvDat$Subject.ID %in% c("RE1249G","RE12634")]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD18X" & vzvDat$Subject.ID %in% c("RE1249G","RE12634")]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD1AQ" & cmvDat$Subject.ID=="RE1406M"]<-"CBD1A0"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1AQ" & cmvDat$Subject.ID=="RE1343M"]<-"RE1343K"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD1AQ" & vzvDat$Subject.ID=="RE1406M"]<-"CBD1A0"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1AQ" & vzvDat$Subject.ID=="RE1343M"]<-"RE1343K"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD1ED" & cmvDat$Subject.ID=="RE14582"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD1ED" & vzvDat$Subject.ID=="RE14582"]<-NA

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1IK" & cmvDat$Subject.ID=="RE15542"]<-"RE1554Z"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1IK" & vzvDat$Subject.ID=="RE15542"]<-"RE1554Z"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1LT" & cmvDat$Subject.ID=="RE17142"]<-"RE1714Z"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1LT" & vzvDat$Subject.ID=="RE17142"]<-"RE1714Z"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD1SD" & cmvDat$Subject.ID=="RE190D"]<-"RE1902R"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD1SD" & vzvDat$Subject.ID=="RE190D"]<-"RE1902R"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBE114" & cmvDat$Subject.ID=="RE1828R"]<-"RE1828F"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBE114" & vzvDat$Subject.ID=="RE1828R"]<-"RE1828F"
cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBE114" & cmvDat$Subject.ID=="RE12424"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBE114" & vzvDat$Subject.ID=="RE12424"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBE115" & cmvDat$Subject.ID=="RE1250U"]<-"CBE11J"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBE115" & vzvDat$Subject.ID=="RE1250U"]<-"CBE11J"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBE11X" & cmvDat$Subject.ID=="RE12561"]<-"RE1256I"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBE11X" & vzvDat$Subject.ID=="RE12561"]<-"RE1256I"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF11J" & cmvDat$Subject.ID=="RE12117"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF11J" & vzvDat$Subject.ID=="RE12117"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF11S" & cmvDat$Subject.ID=="RE1218U"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF11S" & vzvDat$Subject.ID=="RE1218U"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF141" & cmvDat$Subject.ID=="RE1187C"]<-"CBF14I"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF141" & vzvDat$Subject.ID=="RE1187C"]<-"CBF14I"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF14U" & cmvDat$Subject.ID=="RE11173"]<-"CBF140"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF14U" & vzvDat$Subject.ID=="RE11173"]<-"CBF140"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF172" & cmvDat$Subject.ID=="RE1348A"]<-"CBF17Z"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF172" & vzvDat$Subject.ID=="RE1348A"]<-"CBF17Z"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF17F" & cmvDat$Subject.ID=="RE1414M"]<-"CBJ17F" # 24 months sample
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF17F" & vzvDat$Subject.ID=="RE1414M"]<-"CBJ17F"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1ER" & cmvDat$Subject.ID=="RE11253"]<-"CBH1AR" # 12 months sample; wrong LIMS data year
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1ER" & vzvDat$Subject.ID=="RE11253"]<-"CBH1AR"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1EX" & cmvDat$Subject.ID=="RE1585C"]<-"CBF1FX"
cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBF1FX" & cmvDat$Subject.ID=="RE1585C"]<-"RE1585L"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1EX" & vzvDat$Subject.ID=="RE1585C"]<-"CBF1FX"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBF1FX" & vzvDat$Subject.ID=="RE1585C"]<-"RE1585L"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1EY" & cmvDat$Subject.ID=="RE1584N"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1EY" & vzvDat$Subject.ID=="RE1584N"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1GD" & cmvDat$Subject.ID=="RE1576N"]<-"CBF1GB"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1GD" & vzvDat$Subject.ID=="RE1576N"]<-"CBF1GB"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1H8" & cmvDat$Subject.ID=="RE1659H"]<-"CBF1HS"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1H8" & vzvDat$Subject.ID=="RE1659H"]<-"CBF1HS"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1HF" & cmvDat$Subject.ID=="RE1163S"]<-"CBH1HF" # 12 months sample
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1HF" & vzvDat$Subject.ID=="RE1163S"]<-"CBH1HF"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBF1HF" & cmvDat$Subject.ID=="RE1693P"]<-"RE1693D"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBF1HF" & vzvDat$Subject.ID=="RE1693P"]<-"RE1693D"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1I3" & cmvDat$Subject.ID=="RE15370"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1I3" & vzvDat$Subject.ID=="RE15370"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD14S" & cmvDat$Subject.ID=="RE1185G"]<-"CBF14S"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD14S" & vzvDat$Subject.ID=="RE1185G"]<-"CBF14S"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD11B" & cmvDat$Subject.ID=="RE1041C"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD11B" & vzvDat$Subject.ID=="RE1041C"]<-NA

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF18B" & cmvDat$Subject.ID=="RE12610"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF18B" & vzvDat$Subject.ID=="RE12610"]<-NA

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBD195" & cmvDat$Subject.ID=="RE12954"]<-"RE1292A"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBD195" & vzvDat$Subject.ID=="RE12954"]<-"RE1292A"

cmvDat$Subject.ID[cmvDat$Subject.ID.1=="CBF1KE" & cmvDat$Subject.ID=="RE1387X"]<-"RE1812V"
vzvDat$Subject.ID[vzvDat$Subject.ID.1=="CBF1KE" & vzvDat$Subject.ID=="RE1387X"]<-"RE1812V"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF16H" & cmvDat$Subject.ID=="RE1263K"]<-NA
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF16H" & vzvDat$Subject.ID=="RE1263K"]<-NA

# manual removal in line with Laura's email from 2022-08-03
labnos2Remove<-c("0022S082204","0022S081375","0022S079597","0022S081379")
cmvDat<-cmvDat %>% dplyr::filter(!(labno %in% labnos2Remove))
vzvDat<-vzvDat %>% dplyr::filter(!(labno %in% labnos2Remove))

problemlabIDscmv<-names(table(cmvDat$Subject.ID.1)[table(cmvDat$Subject.ID.1)>1]) # 12 left, down from 45 initially; many of these are proper duplicates but often with quite different measurements
problemlabIDsvzv<-names(table(vzvDat$Subject.ID.1)[table(vzvDat$Subject.ID.1)>1]) # 12 left, down from 45 initially; these many of these are proper duplicates but often with quite different measurements

for(ID in problemlabIDscmv){
  idx2remove<-character(0)
  if(sum(grepl(pattern="<|>",cmvDat$Result[cmvDat$Subject.ID.1==ID]))>0){
    idx2remove<-which(cmvDat$Subject.ID.1==ID & grepl(pattern="<|>",cmvDat$Result))
  }else if(sum(grepl(pattern="2022",cmvDat$Sample.Date[cmvDat$Subject.ID.1==ID]))>0){
    idx2remove<-which(cmvDat$Subject.ID.1==ID & !grepl(pattern="2022",cmvDat$Sample.Date))
  }
  if(length(idx2remove)>0){cmvDat<-cmvDat[-idx2remove,]}
}

for(ID in problemlabIDsvzv){
  idx2remove<-character(0)
  if(sum(grepl(pattern="<|>",vzvDat$Result[vzvDat$Subject.ID.1==ID]))>0){
    idx2remove<-which(vzvDat$Subject.ID.1==ID & grepl(pattern="<|>",vzvDat$Result))
  }else if(sum(grepl(pattern="2022",vzvDat$Sample.Date[vzvDat$Subject.ID.1==ID]))>0){
    idx2remove<-which(vzvDat$Subject.ID.1==ID & !grepl(pattern="2022",vzvDat$Sample.Date))
  }
  if(length(idx2remove)>0){vzvDat<-vzvDat[-idx2remove,]}
}

problemlabIDscmv<-names(table(cmvDat$Subject.ID.1)[table(cmvDat$Subject.ID.1)>1]) # 7 left, down from 45 initially; many of these are proper duplicates but often with quite different measurements
problemlabIDsvzv<-names(table(vzvDat$Subject.ID.1)[table(vzvDat$Subject.ID.1)>1]) # 7 left, down from 45 initially; these many of these are proper duplicates but often with quite different measurements

tmp.cmv<-cmvDat %>% dplyr::filter(Subject.ID.1 %in% problemlabIDscmv) 
tmp.vzv<-vzvDat %>% dplyr::filter(Subject.ID.1 %in% problemlabIDsvzv)
#tmp<-rbind(tmp.cmv,tmp.vzv)
#tmp<-tmp[order(tmp$Subject.ID.1),]
#write.csv(tmp,row.names=F,file=paste(sep="_",outPrefix,"CmvVzvProblemLabIDs.csv"))

# remove the duplicated results, before adding back the average values
cmvDat<-cmvDat %>% dplyr::filter(!(Subject.ID.1 %in% problemlabIDscmv))
vzvDat<-vzvDat %>% dplyr::filter(!(Subject.ID.1 %in% problemlabIDsvzv))

# average the duplicate results
tmp.cmv<-tmp.cmv %>%
  dplyr::group_by(Subject.ID) %>%
  dplyr::summarise(
    Source.Code=unique(Source.Code),
    labno=paste(collapse="_",labno),
    Subject.ID.1=unique(Subject.ID.1),
    Sample.Date=unique(Sample.Date),
    Test=unique(Test),
    Result=as.character(mean(as.numeric(Result))),
    Units=unique(Units),
    status=unique(status),
    .groups="drop"
  ) %>%
  dplyr::select(c(Source.Code,labno,Subject.ID,Subject.ID.1,Sample.Date,Test,Result,Units,status))

tmp.vzv<-tmp.vzv %>%
  dplyr::group_by(Subject.ID) %>%
  dplyr::summarise(
    Source.Code=unique(Source.Code),
    labno=paste(collapse="_",labno),
    Subject.ID.1=unique(Subject.ID.1),
    Sample.Date=unique(Sample.Date),
    Test=unique(Test),
    Result=as.character(mean(as.numeric(Result))),
    Units=unique(Units),
    status=unique(status),
    .groups="drop"
  ) %>%
  dplyr::select(c(Source.Code,labno,Subject.ID,Subject.ID.1,Sample.Date,Test,Result,Units,status))

cmvDat<-rbind(cmvDat,tmp.cmv)
vzvDat<-rbind(vzvDat,tmp.vzv)
rm(tmp.cmv,tmp.vzv)

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD15C" & cmvDat$Subject.ID=="RE1307S"]<-"CBD18X"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD15C" & vzvDat$Subject.ID=="RE1307S"]<-"CBD18X"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBE157" & cmvDat$Subject.ID=="RE1283C"]<-"CBD157"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBE157" & vzvDat$Subject.ID=="RE1283C"]<-"CBD157"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD1N2" & cmvDat$Subject.ID=="RE17935"]<-"CBD1N1"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD1N2" & vzvDat$Subject.ID=="RE17935"]<-"CBD1N1"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBD14P" & cmvDat$Subject.ID=="RE1156Q"]<-"CBF14P"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBD14P" & vzvDat$Subject.ID=="RE1156Q"]<-"CBF14P"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1XO" & cmvDat$Subject.ID=="RE1968S"]<-"CBF1X0"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1XO" & vzvDat$Subject.ID=="RE1968S"]<-"CBF1X0"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF1LO" & cmvDat$Subject.ID=="RE1850J"]<-"CBF1L0"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF1LO" & vzvDat$Subject.ID=="RE1850J"]<-"CBF1L0"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBG10W" & cmvDat$Subject.ID=="RE1305W"]<-"CBF17N"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBG10W" & vzvDat$Subject.ID=="RE1305W"]<-"CBF17N"

cmvDat$Subject.ID.1[cmvDat$Subject.ID.1=="CBF17N" & cmvDat$Subject.ID=="RE1307S"]<-"CBF16H"
vzvDat$Subject.ID.1[vzvDat$Subject.ID.1=="CBF17N" & vzvDat$Subject.ID=="RE1307S"]<-"CBF16H"

cmvDat<-cmvDat %>%
  dplyr::mutate(visit=rhiccaDatLong$visit[match(Subject.ID.1,rhiccaDatLong$lims.lab_id)]) %>%
  dplyr::mutate(visit=dplyr::case_when(
    is.na(Subject.ID.1)~NA_character_,
    TRUE~visit
    ))

vzvDat<-vzvDat %>%
  dplyr::mutate(visit=rhiccaDatLong$visit[match(Subject.ID.1,rhiccaDatLong$lims.lab_id)]) %>%
  dplyr::mutate(visit=dplyr::case_when(
    is.na(Subject.ID.1)~NA_character_,
    TRUE~visit
    ))

cmvDat$visit[cmvDat$Subject.ID.1=="CBG19Y" & cmvDat$Subject.ID=="RE1958W"]<-"6months"
vzvDat$visit[vzvDat$Subject.ID.1=="CBG19Y" & vzvDat$Subject.ID=="RE1958W"]<-"6months"

idxMissVisits<-which(is.na(cmvDat$visit) & cmvDat$Subject.ID %in% rhiccaDatLong$pid)
cmvDat$visit[idxMissVisits]<-rhiccaDatLong$visit[match(paste(sep="_",cmvDat$Subject.ID[idxMissVisits],lubridate::dmy(cmvDat$Sample.Date[idxMissVisits])),paste(sep="_",rhiccaDatLong$pid,lubridate::dmy(rhiccaDatLong$physio.data_date)))]

idxMissVisits<-which(is.na(vzvDat$visit) & vzvDat$Subject.ID %in% rhiccaDatLong$pid)
vzvDat$visit[idxMissVisits]<-rhiccaDatLong$visit[match(paste(sep="_",vzvDat$Subject.ID[idxMissVisits],lubridate::dmy(vzvDat$Sample.Date[idxMissVisits])),paste(sep="_",rhiccaDatLong$pid,lubridate::dmy(rhiccaDatLong$physio.data_date)))]

cmvDat<-cmvDat %>% dplyr::filter(Subject.ID %in% rhiccaDatWide$pid)
vzvDat<-vzvDat %>% dplyr::filter(Subject.ID %in% rhiccaDatWide$pid)

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE12858" & cmvDat$Subject.ID.1=="CBG10K"]<-"14/03/2018"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE12858" & vzvDat$Subject.ID.1=="CBG10K"]<-"14/03/2018"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE19711" & cmvDat$Subject.ID.1=="CBG19X"]<-"11/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE19711" & vzvDat$Subject.ID.1=="CBG19X"]<-"11/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1930J" & cmvDat$Subject.ID.1=="CBG19W"]<-"08/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1930J" & vzvDat$Subject.ID.1=="CBG19W"]<-"08/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1922J" & cmvDat$Subject.ID.1=="CBG19S"]<-"06/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1922J" & vzvDat$Subject.ID.1=="CBG19S"]<-"06/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE19287" & cmvDat$Subject.ID.1=="CBG19R"]<-"06/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE19287" & vzvDat$Subject.ID.1=="CBG19R"]<-"06/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE19279" & cmvDat$Subject.ID.1=="CBG19P"]<-"04/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE19279" & vzvDat$Subject.ID.1=="CBG19P"]<-"04/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1926B" & cmvDat$Subject.ID.1=="CBG19N"]<-"01/02/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1926B" & vzvDat$Subject.ID.1=="CBG19N"]<-"01/02/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1870B" & cmvDat$Subject.ID.1=="CBG174"]<-"11/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1870B" & vzvDat$Subject.ID.1=="CBG174"]<-"11/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE18735" & cmvDat$Subject.ID.1=="CBG11Y"]<-"11/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE18735" & vzvDat$Subject.ID.1=="CBG11Y"]<-"11/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE18663" & cmvDat$Subject.ID.1=="CBG171"]<-"10/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE18663" & vzvDat$Subject.ID.1=="CBG171"]<-"10/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1854B" & cmvDat$Subject.ID.1=="CBG170"]<-"09/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1854B" & vzvDat$Subject.ID.1=="CBG170"]<-"09/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1868X" & cmvDat$Subject.ID.1=="CBG172"]<-"10/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1868X" & vzvDat$Subject.ID.1=="CBG172"]<-"10/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE18671" & cmvDat$Subject.ID.1=="CBG173"]<-"10/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE18671" & vzvDat$Subject.ID.1=="CBG173"]<-"10/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1853D" & cmvDat$Subject.ID.1=="CBG17N"]<-"07/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1853D" & vzvDat$Subject.ID.1=="CBG17N"]<-"07/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE18567" & cmvDat$Subject.ID.1=="CBG17P"]<-"08/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE18567" & vzvDat$Subject.ID.1=="CBG17P"]<-"08/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1830R" & cmvDat$Subject.ID.1=="CBG17Q"]<-"08/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1830R" & vzvDat$Subject.ID.1=="CBG17Q"]<-"08/01/2019"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE1762J" & cmvDat$Subject.ID.1=="CBG17E"]<-"10/12/2018"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE1762J" & vzvDat$Subject.ID.1=="CBG17E"]<-"10/12/2018"

cmvDat$Sample.Date[cmvDat$Subject.ID=="RE18655" & cmvDat$Subject.ID.1=="CBG16Z"]<-"09/01/2019"
vzvDat$Sample.Date[vzvDat$Subject.ID=="RE18655" & vzvDat$Subject.ID.1=="CBG16Z"]<-"09/01/2019"

for(j in which(is.na(cmvDat$visit))){
  pid<-cmvDat$Subject.ID[j]
  sdate<-cmvDat$Sample.Date[j]
  j2<-which(rhiccaDatLong$pid==pid & abs(dmy(sdate)-dmy(rhiccaDatLong$physio.data_date))<5)
  j3<-which(vzvDat$Subject.ID==pid & vzvDat$Subject.ID.1==cmvDat$Subject.ID.1[j])
  if(length(j2)==1){
    cmvDat$visit[j]<-rhiccaDatLong$visit[j2]
    if(length(j3)==1){
      vzvDat$visit[j3]<-rhiccaDatLong$visit[j2]
    }
  }
}

colnames(cmvDat)[colnames(cmvDat)=="Result"]<-"cmv"
colnames(cmvDat)[colnames(cmvDat)=="Sample.Date"]<-"data_date"
cmvDat$visit<-factor(cmvDat$visit,levels=c("enrolment","6months","12months","18months","24months","30months","36months"))

colnames(vzvDat)[colnames(vzvDat)=="Result"]<-"vzv"
colnames(vzvDat)[colnames(vzvDat)=="Sample.Date"]<-"data_date"
vzvDat$visit<-factor(vzvDat$visit,levels=c("enrolment","6months","12months","18months","24months","30months","36months"))

cmvDat$cmv[cmvDat$cmv==">2500.0"]<-2500
cmvDat$cmv[cmvDat$cmv=="<0.1"]<-0.1
cmvDat$cmv<-as.numeric(cmvDat$cmv) # will lose one data point ">250.0"

vzvDat$vzv[vzvDat$vzv==">4000.0"]<-4000
vzvDat$vzv[vzvDat$vzv=="<10.0"]<-10.0
vzvDat$vzv<-as.numeric(vzvDat$vzv)

cmvDatWide<-cmvDat %>%
  dplyr::select(!c(Test,Units,status,labno)) %>%
  tidyr::pivot_wider(names_from=visit,values_from=c(cmv,data_date,Subject.ID.1))

vzvDatWide<-vzvDat %>%
  dplyr::select(!c(Test,Units,status,labno)) %>%
  tidyr::pivot_wider(names_from=visit,values_from=c(vzv,data_date,Subject.ID.1))

colnames(cmvDatWide)<-paste(sep=".","cmv",colnames(cmvDatWide))
colnames(vzvDatWide)<-paste(sep=".","vzv",colnames(vzvDatWide))

cmvQuartiles<-quantile(probs=c(0,0.25,0.5,0.75,1),c(cmvDatWide$cmv.cmv_enrolment,cmvDatWide$cmv.cmv_6months),na.rm=TRUE)
vzvQuartiles<-quantile(probs=c(0,0.25,0.5,0.75,1),c(vzvDatWide$vzv.vzv_enrolment,vzvDatWide$vzv.vzv_6months),na.rm=TRUE)

cmvDatWide<-cmvDatWide %>%
  dplyr::mutate(
    cmvStatus=factor(case_when(
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "persistently low titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "progression to low titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "progression to high titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "persistently high titres",
      TRUE~NA_character_
    ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
    cmvEnrolmentStatus=factor(case_when(
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment<cmvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment>=cmvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres"))
  ) %>%
  mutate(
        cmvStatus_2levels=factor(case_when(
          !is.na(cmvStatus) & cmvStatus=="persistently high titres"~"persistently high titres",
          !is.na(cmvStatus) & cmvStatus!="persistently high titres"~"not persistently high titres"
        ),levels=c("not persistently high titres","persistently high titres"))
  )

vzvDatWide<-vzvDatWide %>%
  dplyr::mutate(
    vzvStatus=factor(case_when(
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "persistently low titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "progression to low titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "progression to high titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "persistently high titres",
      TRUE~NA_character_
    ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
    vzvEnrolmentStatus=factor(case_when(
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment<vzvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment>=vzvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres"))
  ) %>%
  mutate(
        vzvStatus_2levels=factor(case_when(
          !is.na(vzvStatus) & vzvStatus=="persistently high titres"~"persistently high titres",
          !is.na(vzvStatus) & vzvStatus!="persistently high titres"~"not persistently high titres"
        ),levels=c("not persistently high titres","persistently high titres"))
  )

rhiccaDatWide<-left_join(rhiccaDatWide,cmvDatWide,by=c("pid"="cmv.Subject.ID"))
rhiccaDatWide<-left_join(rhiccaDatWide,vzvDatWide,by=c("pid"="vzv.Subject.ID"))

rhiccaDatLong<-rhiccaDatLong %>%
  dplyr::mutate(
    cmv.cmv=cmvDat$cmv[match(paste(sep="_",pid,visit),paste(sep="_",cmvDat$Subject.ID,cmvDat$visit))],
    vzv.vzv=vzvDat$vzv[match(paste(sep="_",pid,visit),paste(sep="_",vzvDat$Subject.ID,vzvDat$visit))]
  )

rhiccaDatWide<-rhiccaDatWide %>%
  dplyr::mutate(
    cmv.cmv_CFB=cmv.cmv_6months-cmv.cmv_enrolment,
    vzv.vzv_CFB=vzv.vzv_6months-vzv.vzv_enrolment,
    vlSuppression=case_when(
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months<=1000~"Complete virological suppression",
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months>1000 & lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months>1000~"Incomplete virological suppression",
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months<=1000 & lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months>1000~"Virological resurgence"
    ),
    cd4Restoration=case_when(
      lims.CD4_Absolute_6months<200~"Minimal immune restoration",
      lims.CD4_Absolute_6months>=200 & lims.CD4_Absolute_6months<500~"Partial immune restoration",
      lims.CD4_Absolute_6months>=500~"Full immune restoration"
    )
  )
rhiccaDatWide<-rhiccaDatWide %>%
  dplyr::mutate(
    crf.PLWH=factor(case_when(crf.ptype=="Patient"~"PLWH",crf.ptype=="Control"~"Control")),
    framinghamScore=framinghamScore(rhiccaDatWide)
  )

rhiccaDatLong<-rhiccaDatLong %>%
  dplyr::mutate(
    crf.PLWH=rhiccaDatWide$crf.PLWH[match(pid,rhiccaDatWide$pid)],
    framinghamScore=rhiccaDatWide$framinghamScore[match(pid,rhiccaDatWide$pid)],
    physio.bmi_cat_enrolment=rhiccaDatWide$physio.bmi_cat_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.hypertension_cat_enrolment=rhiccaDatWide$physio.bp_group_enrolment[match(pid,rhiccaDatWide$pid)],
    cmvStatus=rhiccaDatWide$cmvStatus[match(pid,rhiccaDatWide$pid)],
    vzvStatus=rhiccaDatWide$vzvStatus[match(pid,rhiccaDatWide$pid)],
    cmvStatus_2levels=rhiccaDatWide$cmvStatus_2levels[match(pid,rhiccaDatWide$pid)],
    vzvStatus_2levels=rhiccaDatWide$vzvStatus_2levels[match(pid,rhiccaDatWide$pid)],
    cmvEnrolmentStatus=rhiccaDatWide$cmvEnrolmentStatus[match(pid,rhiccaDatWide$pid)],
    vzvEnrolmentStatus=rhiccaDatWide$cmvEnrolmentStatus[match(pid,rhiccaDatWide$pid)],
    eGFR_existingCKD=rhiccaDatWide$eGFR_existingCKD[match(pid,rhiccaDatWide$pid)]
  )

# saving the cleaned, merged data
save(rhiccaDatLong,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_allMerged_longFormat",gsub(pattern="-",replacement="",Sys.Date()),".RData"))
save(rhiccaDatWide,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_allMerged_wideFormat",gsub(pattern="-",replacement="",Sys.Date()),".RData"))
write.csv(rhiccaDatWide,file=paste(sep="","../output/",gsub(pattern="-",replacement="",Sys.Date()),"/rhiccaDat_allMerged_wideFormat",gsub(pattern="-",replacement="",Sys.Date()),".csv"))

The final, cleaned data for analysis consists of 896 participants, of which 710 PLWH and 186 controls.

The total amount for follow-up time for all study participants was 1713.74 person-years, of which 1303.27 person-years were in PLWH and 410.48 in controls.

6.1.2.1 Study flow diagram

We can summarise the LTFU on a flow diagram, shown in Figure 6.2.

include_graphics("../SAP/ConsortDiagram_withTotals_20221109.png")
RHICCA study workflow.

Figure 6.2: RHICCA study workflow.

6.1.3 Participant baseline data and demographics

We can summarise baseline data for most exposures, outcome data and demographics in Table 6.3.

sumFun<-function(.data){
  .data %>%
  dplyr::summarise(n=n(),
            # covariates confounders
            sexMale=sum(na.rm=T,crf.gender=="Male"),
            sexMaleProp=sum(na.rm=T,crf.gender=="Male")/sum(!is.na(crf.gender)),
            sexMaleMV=sum(is.na(crf.gender))/n(),
            ageMedian=median(na.rm=T,crf.age),
            age25th=quantile(na.rm=T,crf.age,probs=0.25),
            age75th=quantile(na.rm=T,crf.age,probs=0.75),
            ageMV=sum(is.na(crf.age))/n(),
            age3545=sum(na.rm=T,crf.age_group=="[35,45)"),
            age3545Prop=sum(na.rm=T,crf.age_group=="[35,45)")/sum(!is.na(crf.age_group)),
            age3545MV=NA,
            age4555=sum(na.rm=T,crf.age_group=="[45,55)"),
            age4555Prop=sum(na.rm=T,crf.age_group=="[45,55)")/sum(!is.na(crf.age_group)),
            age4555MV=NA,
            age5565=sum(na.rm=T,crf.age_group=="[55,65)"),
            age5565Prop=sum(na.rm=T,crf.age_group=="[55,65)")/sum(!is.na(crf.age_group)),
            age5565MV=NA,
            age65=sum(na.rm=T,crf.age_group=="[65,Inf)"),
            age65Prop=sum(na.rm=T,crf.age_group=="[65,Inf)")/sum(!is.na(crf.age_group)),
            age65MV=NA,
            BMIMedian=median(na.rm=T,physio.bmi_enrolment),
            BMI25th=quantile(na.rm=T,physio.bmi_enrolment,probs=0.25),
            BMI75th=quantile(na.rm=T,physio.bmi_enrolment,probs=0.75),
            BMIMV=sum(is.na(physio.bmi_enrolment))/n(),
            WHRMedian=median(na.rm=T,physio.waist_enrolment/physio.hip_enrolment),
            WHR25th=quantile(na.rm=T,physio.waist_enrolment/physio.hip_enrolment,probs=0.25),
            WHR75th=quantile(na.rm=T,physio.waist_enrolment/physio.hip_enrolment,probs=0.75),
            WHRMV=sum(is.na(physio.waist_enrolment/physio.hip_enrolment))/n(),
            bpDiaMean=mean(na.rm=T,physio.bp_dia_enrolment),
            bpDiaSd=sd(na.rm=T,physio.bp_dia_enrolment),
            bpDiaMV=sum(is.na(physio.bp_dia_enrolment))/n(),
            bpSysMean=mean(na.rm=T,physio.bp_sys_enrolment),
            bpSysSd=sd(na.rm=T,physio.bp_sys_enrolment),
            bpSysMV=sum(is.na(physio.bp_sys_enrolment))/n(),
            tensionNormal=sum(na.rm=T,physio.bp_group_enrolment=="Normotensive"),
            tensionNormalProp=sum(na.rm=T,physio.bp_group_enrolment=="Normotensive")/sum(!is.na(physio.bp_group_enrolment)),
            tensionNormalMV=NA,
            tensionPreHyp=sum(na.rm=T,physio.bp_group_enrolment=="Pre-hypertensive"),
            tensionPreHypProp=sum(na.rm=T,physio.bp_group_enrolment=="Pre-hypertensive")/sum(!is.na(physio.bp_group_enrolment)),
            tensionPreHypMV=NA,
            tensionHyp=sum(na.rm=T,physio.bp_group_enrolment=="Hypertensive"),
            tensionHypProp=sum(na.rm=T,physio.bp_group_enrolment=="Hypertensive")/sum(!is.na(physio.bp_group_enrolment)),
            tensionHypMV=NA,
            cholesterolMedian=median(na.rm=T,lims.Cholesterol_enrolment),
            cholesterol25th=quantile(na.rm=T,lims.Cholesterol_enrolment,probs=0.25),
            cholesterol75th=quantile(na.rm=T,lims.Cholesterol_enrolment,probs=0.75),
            cholesterolMV=sum(is.na(lims.Cholesterol_enrolment))/n(),
            hyperchol=sum(na.rm=T,lims.Cholesterol_enrolment>=5.2),
            hypercholProp=sum(na.rm=T,lims.Cholesterol_enrolment>=5.2)/sum(!is.na(lims.Cholesterol_enrolment)),
            hypercholMV=NA,
            glucoseMean=mean(na.rm=T,lims.Glucose_enrolment),
            glucoseSd=sd(na.rm=T,lims.Glucose_enrolment),
            glucoseMV=sum(is.na(lims.Glucose_enrolment))/n(),
            diabetes=sum(na.rm=T,lims.Glucose_enrolment>=11.1),
            diabetesProp=sum(na.rm=T,lims.Glucose_enrolment>=11.1)/sum(!is.na(lims.Glucose_enrolment)),
            diabetesMV=NA,
            eGFRMean=mean(na.rm=T,eGFR_enrolment),
            eGFRSd=sd(na.rm=T,eGFR_enrolment),
            eGFRMV=sum(is.na(eGFR_enrolment))/n(),
            chronKidney=sum(na.rm=T,eGFR_enrolment<60),
            chronKidneyProp=sum(na.rm=T,eGFR_enrolment<60)/sum(!is.na(eGFR_enrolment)),
            chronKidneyMV=NA,
            curSmoke=sum(na.rm=T,crf.smoke=="yes"),
            curSmokeProp=sum(na.rm=T,crf.smoke=="yes")/sum(!is.na(crf.smoke)),
            curSmokeMV=sum(is.na(crf.smoke))/n(),
            alcohol=sum(na.rm=T,crf.alcohol=="yes"),
            alcoholProp=sum(na.rm=T,crf.alcohol=="yes")/sum(!is.na(crf.alcohol)),
            alcoholMV=sum(is.na(crf.alcohol))/n(),
            framHamScoreMedian=median(na.rm=T,framinghamScore),
            framHamScore25th=quantile(na.rm=T,framinghamScore,probs=0.25),
            framHamScore75th=quantile(na.rm=T,framinghamScore,probs=0.75),
            framHamScoreMV=sum(is.na(framinghamScore))/n(),
            
            # covariates primary
            HIVpos=sum(crf.ptype=="Patient"),
            HIVposProp=sum(crf.ptype=="Patient")/sum(!is.na(crf.ptype)),
            HIVposMV=sum(is.na(crf.ptype))/n(),
            HIVvlMedian=median(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment),
            HIVvl25th=quantile(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment,probs=0.25),
            HIVvl75th=quantile(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment,probs=0.75),
            HIVvlMV=sum(is.na(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment))/n(),
            HIVvl_6mts_Median=median(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months),
            HIVvl_6mts_25th=quantile(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months,probs=0.25),
            HIVvl_6mts_75th=quantile(na.rm=T,lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months,probs=0.75),
            HIVvl_6mts_MV=sum(is.na(lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months))/n(),
            CD4Median=median(na.rm=T,lims.CD4_Absolute_enrolment),
            CD425th=quantile(na.rm=T,lims.CD4_Absolute_enrolment,probs=0.25),
            CD475th=quantile(na.rm=T,lims.CD4_Absolute_enrolment,probs=0.75),
            CD4MV=sum(is.na(lims.CD4_Absolute_enrolment))/n(),
            CD4_6mts_Median=median(na.rm=T,lims.CD4_Absolute_6months),
            CD4_6mts_25th=quantile(na.rm=T,lims.CD4_Absolute_6months,probs=0.25),
            CD4_6mts_75th=quantile(na.rm=T,lims.CD4_Absolute_6months,probs=0.75),
            CD4_6mts_MV=sum(is.na(lims.CD4_Absolute_6months))/n(),
            CD163Median=median(na.rm=T,lum.CD163_enrolment),
            CD16325th=quantile(na.rm=T,lum.CD163_enrolment,probs=0.25),
            CD16375th=quantile(na.rm=T,lum.CD163_enrolment,probs=0.75),
            CD163MV=sum(is.na(lum.CD163_enrolment))/n(),
            ICAM1Median=median(na.rm=T,lum.ICAM1_enrolment),
            ICAM125th=quantile(na.rm=T,lum.ICAM1_enrolment,probs=0.25),
            ICAM175th=quantile(na.rm=T,lum.ICAM1_enrolment,probs=0.75),
            ICAM1MV=sum(is.na(lum.ICAM1_enrolment))/n(),
            IL6Median=median(na.rm=T,lum.IL6_enrolment),
            IL625th=quantile(na.rm=T,lum.IL6_enrolment,probs=0.25),
            IL675th=quantile(na.rm=T,lum.IL6_enrolment,probs=0.75),
            IL6MV=sum(is.na(lum.IL6_enrolment))/n(),
            IL1bMedian=median(na.rm=T,lum.ILb_enrolment),
            IL1b25th=quantile(na.rm=T,lum.ILb_enrolment,probs=0.25),
            IL1b75th=quantile(na.rm=T,lum.ILb_enrolment,probs=0.75),
            IL1bMV=sum(is.na(lum.ILb_enrolment))/n(),
            cmvMedian=median(na.rm=T,cmv.cmv_enrolment),
            cmv25th=quantile(na.rm=T,cmv.cmv_enrolment,probs=0.25),
            cmv75th=quantile(na.rm=T,cmv.cmv_enrolment,probs=0.75),
            cmvMV=sum(is.na(cmv.cmv_enrolment))/n(),
            cmvStatusMV=sum(is.na(cmv.cmv_enrolment) | is.na(cmv.cmv_6months))/n(),
            cmvStatusPLow=sum(na.rm=TRUE,cmvStatus=="persistently low titres"),
            cmvStatusPLowProp=sum(na.rm=TRUE,cmvStatus=="persistently low titres")/sum(!is.na(cmvStatus)),
            cmvStatusPLowMV=NA,
            cmvStatusPLat=sum(na.rm=TRUE,cmvStatus=="progression to low titres"),
            cmvStatusPLatProp=sum(na.rm=TRUE,cmvStatus=="progression to low titres")/sum(!is.na(cmvStatus)),
            cmvStatusPLatMV=NA,
            cmvStatusRLat=sum(na.rm=TRUE,cmvStatus=="progression to high titres"),
            cmvStatusRLatProp=sum(na.rm=TRUE,cmvStatus=="progression to high titres")/sum(!is.na(cmvStatus)),
            cmvStatusRLatMV=NA,
            cmvStatusPHigh=sum(na.rm=TRUE,cmvStatus=="persistently high titres"),
            cmvStatusPHighProp=sum(na.rm=TRUE,cmvStatus=="persistently high titres")/sum(!is.na(cmvStatus)),
            cmvStatusPHighMV=NA,
            vzvMedian=median(na.rm=T,vzv.vzv_enrolment),
            vzv25th=quantile(na.rm=T,vzv.vzv_enrolment,probs=0.25),
            vzv75th=quantile(na.rm=T,vzv.vzv_enrolment,probs=0.75),
            vzvMV=sum(is.na(vzv.vzv_enrolment))/n(),
            vzvStatusMV=sum(is.na(vzv.vzv_enrolment) | is.na(vzv.vzv_6months))/n(),
            vzvStatusPLow=sum(na.rm=TRUE,vzvStatus=="persistently low titres"),
            vzvStatusPLowProp=sum(na.rm=TRUE,vzvStatus=="persistently low titres")/sum(!is.na(vzvStatus)),
            vzvStatusPLowMV=NA,
            vzvStatusPLat=sum(na.rm=TRUE,vzvStatus=="progression to low titres"),
            vzvStatusPLatProp=sum(na.rm=TRUE,vzvStatus=="progression to low titres")/sum(!is.na(vzvStatus)),
            vzvStatusPLatMV=NA,
            vzvStatusRLat=sum(na.rm=TRUE,vzvStatus=="progression to high titres"),
            vzvStatusRLatProp=sum(na.rm=TRUE,vzvStatus=="progression to high titres")/sum(!is.na(cmvStatus)),
            vzvStatusRLatMV=NA,
            vzvStatusPHigh=sum(na.rm=TRUE,vzvStatus=="persistently high titres"),
            vzvStatusPHighProp=sum(na.rm=TRUE,vzvStatus=="persistently high titres")/sum(!is.na(vzvStatus)),
            vzvStatusPHighMV=NA,
            
            # endpoints
            PWVMean=mean(na.rm=T,pwv.pwv_enrolment),
            PWVSd=sd(na.rm=T,pwv.pwv_enrolment),
            PWVMV=sum(is.na(pwv.pwv_enrolment))/n(),
            CIMTMean=mean(na.rm=T,cimt.cimt_enrolment),
            CIMTSd=sd(na.rm=T,cimt.cimt_enrolment),
            CIMTMV=sum(is.na(cimt.cimt_enrolment))/n(),
            ABPIMean=mean(na.rm=T,abpi.abpi_enrolment),
            ABPISd=sd(na.rm=T,abpi.abpi_enrolment),
            ABPIMV=sum(is.na(abpi.abpi_enrolment))/n(),
            clinEvents=sum(na.rm=T,numClinEventsPerParticipant),
            clinEventsPer100Participants=100*sum(na.rm=T,numClinEventsPerParticipant)/sum(!is.na(numClinEventsPerParticipant)),
            clinEventsMV=sum(is.na(numClinEventsPerParticipant))/n(),
            clinEventsConfirmedCVD=sum(na.rm=T,numClinEventsConfirmedPerParticipantCVD),
            clinEventsConfirmedCVDPer1000PYs=1000*365.25*sum(na.rm=T,numClinEventsConfirmedPerParticipantCVD)/sum(na.rm=T,as.numeric(obsTime)),
            clinEventsConfirmedCVDMV=sum(is.na(numClinEventsConfirmedPerParticipant))/n(),
            clinEventsConfirmedCVDWithCIMT=sum(na.rm=T,numClinEventsConfirmedPerParticipantCVDwithCIMT),
            clinEventsConfirmedCVDWithCIMTPer1000PYs=1000*365.25*sum(na.rm=T,numClinEventsConfirmedPerParticipantCVDwithCIMT)/sum(na.rm=T,as.numeric(obsTime)),
            clinEventsConfirmedCVDWithCIMTMV=sum(is.na(numClinEventsConfirmedPerParticipantCVDwithCIMT))/n(),
            clinEventsCimt=sum(na.rm=T,numClinEventsCimt),
            clinEventsCimtPer1000PYs=1000*365.25*sum(na.rm=T,numClinEventsCimt)/sum(na.rm=T,as.numeric(obsTime)),
            clinEventsCimtMV=sum(is.na(numClinEventsCimt))/n(),
            
            # follow-up
            followUp24mts=sum(ltfu_24months==0),
            followUp24mtsProp=sum(ltfu_24months==0)/n(),
            followUp24mtsMV=NA,
            .groups="drop")
}

demoDatAll<-rhiccaDatWide %>%
  filter(ltfu_enrolment==0) %>%
  sumFun()

demoDatStrat<-rhiccaDatWide %>%
  filter(ltfu_enrolment==0) %>%
  group_by(crf.ptype) %>%
  sumFun()

demoDatSummary<-rbind(data.frame(crf.ptype="All",demoDatAll),demoDatStrat)


reformatFun<-function(dat,var,type,rowIdx,roundDigits=NULL){
  # type needs to be one of "medianIQR", "meanSD", "nProp"
  if(type=="medianIQR"){
    if(is.null(roundDigits)){roundDigits=1}
    tmp<-as.numeric(dat[rowIdx,paste(sep="",var,c("MV","Median","25th","75th"))]) 
    tmp<-c(paste(sep="",format(nsmall=1,round(100*tmp[1],digits=1)),"%"),format(nsmall=roundDigits,round(tmp[2],digits=roundDigits)),paste(sep="","(",format(nsmall=roundDigits,round(tmp[3],digits=roundDigits)),"-",format(nsmall=roundDigits,round(tmp[4],digits=roundDigits)),")"))
  }else if(type=="medianIQRbignum"){
    if(is.null(roundDigits)){roundDigits=1}
    tmp<-as.numeric(dat[rowIdx,paste(sep="",var,c("MV","Median","25th","75th"))]) 
    tmp<-c(paste(sep="",format(nsmall=1,round(100*tmp[1],digits=1)),"%"),format(big.mark=",",nsmall=roundDigits,round(tmp[2],digits=roundDigits)),paste(sep="","(",format(big.mark=",",nsmall=roundDigits,round(tmp[3],digits=roundDigits)),"-",format(big.mark=",",nsmall=roundDigits,round(tmp[4],digits=roundDigits)),")"))
  }else if(type=="medianIQRperc"){
    if(is.null(roundDigits)){roundDigits=1}
    tmp<-as.numeric(dat[rowIdx,paste(sep="",var,c("MV","Median","25th","75th"))]) 
    tmp<-c(paste(sep="",format(nsmall=1,round(100*tmp[1],digits=1)),"%"),paste(sep="",format(nsmall=roundDigits,round(100*tmp[2],digits=roundDigits)),"%"),paste(sep="","(",paste(sep="",format(nsmall=roundDigits,round(100*tmp[3],digits=roundDigits)),"%"),"-",paste(sep="",format(nsmall=roundDigits,round(100*tmp[4],digits=roundDigits)),"%"),")"))
  }else if(type=="meanSD"){
    if(is.null(roundDigits)){roundDigits=1}
    tmp<-as.numeric(dat[rowIdx,paste(sep="",var,c("MV","Mean","Sd"))])
    tmp<-c(paste(sep="",format(nsmall=1,round(100*tmp[1],digits=1)),"%"),format(nsmall=roundDigits,round(tmp[2],digits=roundDigits)),paste(sep="","(",format(nsmall=roundDigits,round(tmp[3],digits=roundDigits)),")"))
  }else if(type=="nProp"){
    if(is.null(roundDigits)){roundDigits=1}
    tmp<-as.numeric(dat[rowIdx,paste(sep="",var,c("MV","","Prop"))])
    tmp<-c(paste(sep="",format(nsmall=1,round(100*tmp[1],digits=1)),"%"),tmp[2],paste(sep="","(",format(nsmall=roundDigits,round(100*tmp[3],digits=roundDigits)),"%)"))
  }
  
  tmp[tmp=="NA%"]<-NA
  
  return(tmp)
}

demoDatKable<-data.frame(
  variable=c("Participants","Followed-up at 24 months","Sex: male","Age","Age group [35,45)","Age group [45,55)","Age group [55,65)","Age group 65+","BMI (kg/m^2^)","Waist-hip ratio","Diastolic blood pressure (mm Hg)","Systolic blood pressure (mm Hg)","Blood pressure: normotensive","Blood pressure: pre-hypertensive","Blood pressure: hypertensive","Cholesterol (mmol/l)","Hypercholesteremic","Glucose (mmol/l)","Diabetic","eGFR (ml/min/1.73m^2^)","Chronic kidney disease","Current smoker","Drink alcohol","Framingham 10-year CVD risk","HIV infected","HIV viral load at baseline (copies/ml)","HIV viral load at 6 months (copies/ml)","HIV CD4+ at baseline (cells/mm^3^)","HIV CD4+ at 6 months (cells/mm^3^)","CD163 (ng/ml)","ICAM-1 (pg/ml)","IL-6 (pg/ml)","IL-1b (pg/ml)","CMV (AU/ml)","CMV status","CMV status: persistently low titres","CMV status: progression to low titres","CMV status: progression to high titres","CMV status: persistently high titres","VZV (mIU/ml)","VZV status","VZV status: persistently low titres","VZV status: progression to low titres","VZV status: progression to high titres","VZV status: persistently high titres","PWV (m/s)","CIMT (mm)","ABPI","Confirmed clinical CVD/CBD events","Sub-clinical CIMT events","Sub-/clinical CVD/CBD events"),
  statistics=c("n (% out of total)","n (%)","n (%)","median (IQR)","n (%)","n (%)","n (%)","n (%)","median (IQR)","median (IQR)","mean (SD)","mean (SD)","n (%)","n (%)","n (%)","median (IQR)","n (%)","mean (SD)","n (%)","mean (SD)","n (%)","n (%)","n (%)","median (IQR)","n (%)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","median (IQR)","","n (%)","n (%)","n (%)","n (%)","median (IQR)","","n (%)","n (%)","n (%)","n (%)","mean (SD)","mean (SD)","mean (SD)","n (events per 1,000 person-years)","n (events per 1,000 person-years)","n (events per 1,000 person-years)"),
  AMV=NA,
  Astat1=NA,
  Astat2=NA,
  PMV=NA,
  Pstat1=NA,
  Pstat2=NA,
  CNA=NA,
  Cstat1=NA,
  Cstat2=NA
)

demoDatKable[1,-c(1,2)]<-c(NA,sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype)),
                           paste(sep="","(",format(nsmall=1,round(100*sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype))/sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype)),digits=1)),"%)"),
                           NA,sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype) & rhiccaDatWide$crf.ptype=="Patient"),
                           paste(sep="","(",format(nsmall=1,round(100*sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype) & rhiccaDatWide$crf.ptype=="Patient")/sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype)),digits=1)),"%)"),
                           NA,sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype) & rhiccaDatWide$crf.ptype=="Control"),
                           paste(sep="","(",format(nsmall=1,round(100*sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype) & rhiccaDatWide$crf.ptype=="Control")/sum(rhiccaDatWide$ltfu_enrolment==0 & !is.na(rhiccaDatWide$crf.ptype)),digits=1)),"%)"))

demoDatKable[demoDatKable$variable=="Followed-up at 24 months",-c(1,2)]<-c(reformatFun(dat=demoDatSummary,var="followUp24mts",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="followUp24mts",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="followUp24mts",type="nProp",rowIdx=2))

demoDatKable[demoDatKable$variable=="Sex: male",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="sexMale",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="sexMale",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="sexMale",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Age",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="age",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="age",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="age",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="Age group [35,45)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="age3545",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="age3545",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="age3545",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Age group [45,55)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="age4555",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="age4555",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="age4555",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Age group [55,65)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="age5565",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="age5565",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="age5565",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Age group 65+",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="age65",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="age65",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="age65",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="BMI (kg/m^2^)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="BMI",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="BMI",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="BMI",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="Waist-hip ratio",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="WHR",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="WHR",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="WHR",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="Diastolic blood pressure (mm Hg)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="bpDia",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="bpDia",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="bpDia",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="Systolic blood pressure (mm Hg)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="bpSys",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="bpSys",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="bpSys",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="Blood pressure: normotensive",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="tensionNormal",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="tensionNormal",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="tensionNormal",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Blood pressure: pre-hypertensive",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="tensionPreHyp",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="tensionPreHyp",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="tensionPreHyp",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Blood pressure: hypertensive",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="tensionHyp",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="tensionHyp",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="tensionHyp",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Cholesterol (mmol/l)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cholesterol",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="cholesterol",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="cholesterol",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="Hypercholesteremic",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="hyperchol",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="hyperchol",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="hyperchol",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Glucose (mmol/l)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="glucose",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="glucose",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="glucose",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="Diabetic",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="diabetes",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="diabetes",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="diabetes",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="eGFR (ml/min/1.73m^2^)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="eGFR",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="eGFR",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="eGFR",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="Chronic kidney disease",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="chronKidney",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="chronKidney",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="chronKidney",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Current smoker",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="curSmoke",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="curSmoke",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="curSmoke",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Drink alcohol",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="alcohol",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="alcohol",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="alcohol",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="Framingham 10-year CVD risk",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="framHamScore",type="medianIQRperc",rowIdx=1),reformatFun(dat=demoDatSummary,var="framHamScore",type="medianIQRperc",rowIdx=3),reformatFun(dat=demoDatSummary,var="framHamScore",type="medianIQRperc",rowIdx=2))
demoDatKable[demoDatKable$variable=="HIV infected",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="HIVpos",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="HIVpos",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="HIVpos",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="HIV viral load at baseline (copies/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="HIVvl",type="medianIQRbignum",rowIdx=1,roundDigits=0),reformatFun(dat=demoDatSummary,var="HIVvl",type="medianIQRbignum",rowIdx=3,roundDigits=0),reformatFun(dat=demoDatSummary,var="HIVvl",type="medianIQRbignum",rowIdx=2,roundDigits=0))
demoDatKable[demoDatKable$variable=="HIV viral load at 6 months (copies/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="HIVvl_6mts_",type="medianIQRbignum",rowIdx=1,roundDigits=0),reformatFun(dat=demoDatSummary,var="HIVvl_6mts_",type="medianIQRbignum",rowIdx=3,roundDigits=0),reformatFun(dat=demoDatSummary,var="HIVvl_6mts_",type="medianIQRbignum",rowIdx=2,roundDigits=0))
demoDatKable[demoDatKable$variable=="HIV CD4+ at baseline (cells/mm^3^)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="CD4",type="medianIQRbignum",rowIdx=1,roundDigits=0),reformatFun(dat=demoDatSummary,var="CD4",type="medianIQRbignum",rowIdx=3,roundDigits=0),reformatFun(dat=demoDatSummary,var="CD4",type="medianIQRbignum",rowIdx=2,roundDigits=0))
demoDatKable[demoDatKable$variable=="HIV CD4+ at 6 months (cells/mm^3^)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="CD4_6mts_",type="medianIQRbignum",rowIdx=1,roundDigits=0),reformatFun(dat=demoDatSummary,var="CD4_6mts_",type="medianIQRbignum",rowIdx=3,roundDigits=0),reformatFun(dat=demoDatSummary,var="CD4_6mts_",type="medianIQRbignum",rowIdx=2,roundDigits=0))
demoDatKable[demoDatKable$variable=="CD163 (ng/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="CD163",type="medianIQRbignum",rowIdx=1),reformatFun(dat=demoDatSummary,var="CD163",type="medianIQRbignum",rowIdx=3),reformatFun(dat=demoDatSummary,var="CD163",type="medianIQRbignum",rowIdx=2))
demoDatKable[demoDatKable$variable=="ICAM-1 (pg/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="ICAM1",type="medianIQRbignum",rowIdx=1),reformatFun(dat=demoDatSummary,var="ICAM1",type="medianIQRbignum",rowIdx=3),reformatFun(dat=demoDatSummary,var="ICAM1",type="medianIQRbignum",rowIdx=2))
demoDatKable[demoDatKable$variable=="IL-6 (pg/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="IL6",type="medianIQRbignum",rowIdx=1),reformatFun(dat=demoDatSummary,var="IL6",type="medianIQRbignum",rowIdx=3),reformatFun(dat=demoDatSummary,var="IL6",type="medianIQRbignum",rowIdx=2))
demoDatKable[demoDatKable$variable=="IL-1b (pg/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="IL1b",type="medianIQRbignum",rowIdx=1),reformatFun(dat=demoDatSummary,var="IL1b",type="medianIQRbignum",rowIdx=3),reformatFun(dat=demoDatSummary,var="IL1b",type="medianIQRbignum",rowIdx=2))
demoDatKable[demoDatKable$variable=="CMV (AU/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cmv",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="cmv",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="cmv",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="CMV status",-c(1:2)]<-c(paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[1,"cmvStatusMV"])),"%"),NA,NA,paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[3,"cmvStatusMV"])),"%"),NA,NA,paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[2,"cmvStatusMV"])),"%"),NA,NA)
demoDatKable[demoDatKable$variable=="CMV status: persistently low titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cmvStatusPLow",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="cmvStatusPLow",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="cmvStatusPLow",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="CMV status: progression to low titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cmvStatusPLat",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="cmvStatusPLat",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="cmvStatusPLat",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="CMV status: progression to high titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cmvStatusRLat",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="cmvStatusRLat",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="cmvStatusRLat",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="CMV status: persistently high titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="cmvStatusPHigh",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="cmvStatusPHigh",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="cmvStatusPHigh",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="VZV (mIU/ml)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="vzv",type="medianIQR",rowIdx=1),reformatFun(dat=demoDatSummary,var="vzv",type="medianIQR",rowIdx=3),reformatFun(dat=demoDatSummary,var="vzv",type="medianIQR",rowIdx=2))
demoDatKable[demoDatKable$variable=="VZV status",-c(1:2)]<-c(paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[1,"vzvStatusMV"])),"%"),NA,NA,paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[3,"vzvStatusMV"])),"%"),NA,NA,paste(sep="",format(nsmall=1,round(digits=1,100*demoDatSummary[2,"vzvStatusMV"])),"%"),NA,NA)
demoDatKable[demoDatKable$variable=="VZV status: persistently low titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="vzvStatusPLow",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="vzvStatusPLow",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="vzvStatusPLow",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="VZV status: progression to low titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="vzvStatusPLat",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="vzvStatusPLat",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="vzvStatusPLat",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="VZV status: progression to high titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="vzvStatusRLat",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="vzvStatusRLat",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="vzvStatusRLat",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="VZV status: persistently high titres",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="vzvStatusPHigh",type="nProp",rowIdx=1),reformatFun(dat=demoDatSummary,var="vzvStatusPHigh",type="nProp",rowIdx=3),reformatFun(dat=demoDatSummary,var="vzvStatusPHigh",type="nProp",rowIdx=2))
demoDatKable[demoDatKable$variable=="PWV (m/s)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="PWV",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="PWV",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="PWV",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="CIMT (mm)",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="CIMT",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="CIMT",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="CIMT",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="ABPI",-c(1:2)]<-c(reformatFun(dat=demoDatSummary,var="ABPI",type="meanSD",rowIdx=1),reformatFun(dat=demoDatSummary,var="ABPI",type="meanSD",rowIdx=3),reformatFun(dat=demoDatSummary,var="ABPI",type="meanSD",rowIdx=2))
demoDatKable[demoDatKable$variable=="Confirmed clinical CVD/CBD events",-c(1:2)]<-c(NA,demoDatSummary[1,"clinEventsConfirmedCVD"],format(nsmall=1,round(demoDatSummary[1,"clinEventsConfirmedCVDPer1000PYs"],digits=1)),NA,demoDatSummary[3,"clinEventsConfirmedCVD"],format(nsmall=1,round(demoDatSummary[3,"clinEventsConfirmedCVDPer1000PYs"],digits=1)),NA,demoDatSummary[2,"clinEventsConfirmedCVD"],format(nsmall=1,round(demoDatSummary[2,"clinEventsConfirmedCVDPer1000PYs"],digits=1)))
demoDatKable[demoDatKable$variable=="Sub-clinical CIMT events",-c(1:2)]<-c(NA,demoDatSummary[1,"clinEventsCimt"],format(nsmall=1,round(demoDatSummary[1,"clinEventsCimtPer1000PYs"],digits=1)),NA,demoDatSummary[3,"clinEventsCimt"],format(nsmall=1,round(demoDatSummary[3,"clinEventsCimtPer1000PYs"],digits=1)),NA,demoDatSummary[2,"clinEventsCimt"],format(nsmall=1,round(demoDatSummary[2,"clinEventsCimtPer1000PYs"],digits=1)))
demoDatKable[demoDatKable$variable=="Sub-/clinical CVD/CBD events",-c(1:2)]<-c(NA,demoDatSummary[1,"clinEventsConfirmedCVDWithCIMT"],format(nsmall=1,round(demoDatSummary[1,"clinEventsConfirmedCVDWithCIMTPer1000PYs"],digits=1)),NA,demoDatSummary[3,"clinEventsConfirmedCVDWithCIMT"],format(nsmall=1,round(demoDatSummary[3,"clinEventsConfirmedCVDWithCIMTPer1000PYs"],digits=1)),NA,demoDatSummary[2,"clinEventsConfirmedCVDWithCIMT"],format(nsmall=1,round(demoDatSummary[2,"clinEventsConfirmedCVDWithCIMTPer1000PYs"],digits=1)))

options(knitr.kable.NA = '')

demoDatKable %>%
  kable(col.names=rep("",ncol(demoDatKable)),caption="Participant characteristics (at baseline).") %>%
  kable_styling(full_width=F) %>%
  add_header_above(c(" "," ","Missing values"," "=2,"Missing values"," "=2,"Missing values"," "=2)) %>%
  add_header_above(c(" "," ","All"=3,"PLWH"=3,"Controls"=3)) %>%
  pack_rows("Non-modifiable risk factors",3,8) %>%
  pack_rows("Modifiable risk factors",9,23) %>%
  pack_rows("Framingham risk score",24,24) %>%
  pack_rows("Exposure variables",25,29) %>%
  pack_rows("Mediators",30,33) %>%
  pack_rows("Mediators - herpes",34,45) %>%
  pack_rows("Outcomes",46,49)
Table 6.3: Participant characteristics (at baseline).
All
PLWH
Controls
Missing values
Missing values
Missing values
Participants n (% out of total) 896 (100.0%) 710 (79.2%) 186 (20.8%)
Followed-up at 24 months n (%) 671 (74.9%) 520 (73.2%) 151 (81.2%)
Non-modifiable risk factors
Sex: male n (%) 0.0% 540 (60.3%) 0.0% 445 (62.7%) 0.0% 95 (51.1%)
Age median (IQR) 0.0% 42.0 (38.0-48.0) 0.0% 42.0 (38.0-47.0) 0.0% 43.0 (38.2-49.0)
Age group [35,45) n (%) 556 (62.1%) 449 (63.2%) 107 (57.5%)
Age group [45,55) n (%) 244 (27.2%) 196 (27.6%) 48 (25.8%)
Age group [55,65) n (%) 67 (7.5%) 51 (7.2%) 16 (8.6%)
Age group 65+ n (%) 29 (3.2%) 14 (2.0%) 15 (8.1%)
Modifiable risk factors
BMI (kg/m2) median (IQR) 0.0% 21.7 (19.6-25.2) 0.0% 21.2 (19.4-24.0) 0.0% 25.3 (21.6-29.8)
Waist-hip ratio median (IQR) 0.0% 0.8 (0.8-0.9) 0.0% 0.8 (0.8-0.9) 0.0% 0.9 (0.8-0.9)
Diastolic blood pressure (mm Hg) mean (SD) 0.0% 78.5 (12.4) 0.0% 77.4 (12.2) 0.0% 82.9 (12.0)
Systolic blood pressure (mm Hg) mean (SD) 0.0% 117.9 (20.0) 0.0% 115.6 (19.3) 0.0% 126.8 (20.3)
Blood pressure: normotensive n (%) 465 (51.9%) 403 (56.8%) 62 (33.3%)
Blood pressure: pre-hypertensive n (%) 272 (30.4%) 197 (27.7%) 75 (40.3%)
Blood pressure: hypertensive n (%) 159 (17.7%) 110 (15.5%) 49 (26.3%)
Cholesterol (mmol/l) median (IQR) 1.3% 3.8 (3.2-4.6) 1.3% 3.6 (3.0-4.3) 1.6% 4.8 (4.0-5.5)
Hypercholesteremic n (%) 118 (13.3%) 60 (8.6%) 58 (31.7%)
Glucose (mmol/l) mean (SD) 1.1% 5.2 (1.9) 1.4% 5.2 (1.9) 0.0% 5.1 (1.7)
Diabetic n (%) 9 (1.0%) 6 (0.9%) 3 (1.6%)
eGFR (ml/min/1.73m2) mean (SD) 0.4% 104.3 (20.3) 0.6% 104.2 (20.5) 0.0% 104.8 (19.3)
Chronic kidney disease n (%) 40 (4.5%) 32 (4.5%) 8 (4.3%)
Current smoker n (%) 0.0% 98 (10.9%) 0.0% 81 (11.4%) 0.0% 17 (9.1%)
Drink alcohol n (%) 0.0% 180 (20.1%) 0.0% 157 (22.1%) 0.0% 23 (12.4%)
Framingham risk score
Framingham 10-year CVD risk median (IQR) 12.1% 3.6% (2.0%-6.1%) 11.4% 3.5% (2.0%-5.8%) 14.5% 4.0% (2.3%-7.8%)
Exposure variables
HIV infected n (%) 0.0% 710 (79.2%) 0.0% 710 (100.0%) 0.0% 0 (0.0%)
HIV viral load at baseline (copies/ml) median (IQR) 23.0% 55,579 (6,472-225,919) 2.8% 55,579 (6,472-225,919) 100.0% NA (NA-NA)
HIV viral load at 6 months (copies/ml) median (IQR) 32.9% 1 (1-1) 15.5% 1 (1-1) 99.5% 1 (1-1)
HIV CD4+ at baseline (cells/mm3) median (IQR) 21.8% 192 (107-312) 1.3% 192 (107-312) 100.0% NA (NA-NA)
HIV CD4+ at 6 months (cells/mm3) median (IQR) 32.6% 294 (203-436) 15.1% 293 (202-436) 99.5% 441 (441-441)
Mediators
CD163 (ng/ml) median (IQR) 19.1% 73.4 (51.3-115.3) 18.3% 76.7 (54.0-129.1) 22.0% 61.1 (45.7-80.3)
ICAM-1 (pg/ml) median (IQR) 18.9% 69,674.6 (40,453.0-150,446.7) 18.0% 68,619.5 (39,395.7-150,593.5) 22.0% 74,474.0 (43,993.5-150,037.4)
IL-6 (pg/ml) median (IQR) 18.9% 2.4 (1.2-4.0) 18.0% 2.4 (1.2-4.9) 22.0% 1.8 (0.9-2.4)
IL-1b (pg/ml) median (IQR) 19.0% 2.4 (0.7-2.4) 18.0% 2.4 (0.7-2.4) 22.6% 2.4 (0.7-2.4)
Mediators - herpes
CMV (AU/ml) median (IQR) 12.7% 322.4 (180.8-868.7) 13.0% 527.5 (198.0-998.5) 11.8% 193.7 (145.2-345.9)
CMV status 43.2% 42.0% 47.8%
CMV status: persistently low titres n (%) 336 (66.0%) 244 (59.2%) 92 (94.8%)
CMV status: progression to low titres n (%) 11 (2.2%) 11 (2.7%) 0 (0.0%)
CMV status: progression to high titres n (%) 68 (13.4%) 65 (15.8%) 3 (3.1%)
CMV status: persistently high titres n (%) 94 (18.5%) 92 (22.3%) 2 (2.1%)
VZV (mIU/ml) median (IQR) 12.8% 1143.0 (731.9-1832.0) 13.1% 1235.0 (759.3-1893.0) 11.8% 896.2 (628.8-1365.5)
VZV status 43.2% 41.8% 48.4%
VZV status: persistently low titres n (%) 343 (67.4%) 267 (64.6%) 76 (79.2%)
VZV status: progression to low titres n (%) 59 (11.6%) 51 (12.3%) 8 (8.3%)
VZV status: progression to high titres n (%) 22 (4.3%) 21 (5.1%) 1 (1.0%)
VZV status: persistently high titres n (%) 85 (16.7%) 74 (17.9%) 11 (11.5%)
Outcomes
PWV (m/s) mean (SD) 1.8% 9.0 (1.8) 1.3% 9.0 (1.7) 3.8% 9.2 (2.1)
CIMT (mm) mean (SD) 0.4% 0.5 (0.1) 0.6% 0.5 (0.1) 0.0% 0.5 (0.1)
ABPI mean (SD) 1.0% 1.0 (0.1) 1.3% 1.0 (0.1) 0.0% 1.0 (0.1)
Confirmed clinical CVD/CBD events n (events per 1,000 person-years) 9 5.3 8 6.1 1 2.4
Sub-clinical CIMT events n (events per 1,000 person-years) 11 6.4 9 6.9 2 4.9
Sub-/clinical CVD/CBD events n (events per 1,000 person-years) 20 11.7 17 13.0 3 7.3
#write.csv(demoDatKable,row.names=F,file=paste(sep="_",outPrefix,"participantCharacteristicsTable_Table1.csv"))
write_excel_csv(demoDatKable,file=paste(sep="_",outPrefix,"participantCharacteristicsTable_Table1.csv"))

6.1.3.1 CMV and VZV categories

In the analyses below we defined categories of CMV / VZV infection status, based on titres measured at enrolment and 6 month:

  • Persistently low titres: titres at both enrolment and 6 month in the bottom 3 quartiles of the data
  • Progression to low titres: titres at enrolment in the top quartile of values and titres at 6 months in bottom 3 quartiles
  • Progression to high titres: titres at enrolment in the bottom 3 quartiles of values and titres at 6 months in the top quartile
  • Persistently high titres: titres at both enrolment and 6 month in the top quartile of the data

6.1.4 Multiple imputation

We have used the R package mice to perform the multiple imputation. Specifically, we use univariate models via fully conditional specification (FCS); i.e. variable-by-variable imputation. This provides a statistically principled basis to perform analysis.

Missing data patterns are summarised visually on Figure 6.3.

impVars <- c("pid","crf.ptype","crf.age","crf.gender","crf.height",grep(value=T,colnames(rhiccaDatWide),pattern="physio.bmi_enrolment|physio.bmi_[0-9]+months|physio.waisthip|physio.hr|physio.temp|physio.bp_dia|physio.bp_sys|pwv.pwv_enrolment|pwv.pwv_[0-9]+months|cimt.cimt_enrolment|cimt.cimt_[0-9]+months|abpi.abpi_enrolment|abpi.abpi_[0-9]+months|eGFR|lims.CD4_Absolute|lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment|lims.Glucose_enrolment|lims.Glucose_[0-9]+months|lims.Cholesterol|lum.CD163_|lum.ICAM1_|lum.IL6_|lum.ILb_|iris|cmv.cmv_|vzv.vzv_"))

impVars<-impVars[!grepl(impVars,pattern="_30months") & !grepl(impVars,pattern="_36months")]
impVars<-setdiff(impVars,c("cmv.cmv_12months","cmv.cmv_24months","cmv.cmv_NA","vzv.vzv_12months","vzv.vzv_24months","vzv.vzv_NA"))
impVars<-c(impVars,"cmvStatus","vzvStatus")

impDat<-rhiccaDatWide %>%
  dplyr::select(all_of(impVars))
impDat<-impDat %>%
  filter(!is.na(crf.ptype) & !is.na(crf.age) & !is.na(crf.gender))

mdPattern<-md.pattern(impDat,plot=F)
missValsPerPattern=mdPattern[-nrow(mdPattern),ncol(mdPattern)]
missValsPerVar=mdPattern[nrow(mdPattern),-ncol(mdPattern)]
missValsPerVarProp=format(nsmall=2,round(digits=2,mdPattern[nrow(mdPattern),-ncol(mdPattern)]/nrow(impDat)))
mdPattern<-mdPattern[-nrow(mdPattern),-ncol(mdPattern)]
mdPatternIdx<-order(missValsPerPattern)
mdPattern<-mdPattern[mdPatternIdx,]
missValsPerPattern<-missValsPerPattern[mdPatternIdx]

mdPatternGg<-data.frame(
  x=as.vector(matrix(nrow=nrow(mdPattern),ncol=ncol(mdPattern),rep(1:ncol(mdPattern),nrow(mdPattern)),byrow=T)),
  y=rep(nrow(mdPattern):1,ncol(mdPattern)),
  z=as.vector(mdPattern)
)

g<-mdPatternGg %>%
  as.data.frame() %>%
  ggplot(mapping=aes(x=x, y=y, fill=as.factor(z))) +
  geom_tile(color="darkgrey",show.legend=F) +
  geom_text(data=data.frame(x=1:ncol(mdPattern),y=nrow(mdPattern)+1,label=colnames(mdPattern),z=NA),mapping=aes(x=x,y=y,label=label),size=2,angle=60,hjust=0) +
  geom_text(data=data.frame(x=1:ncol(mdPattern),y=0,label=missValsPerVarProp,z=NA),mapping=aes(x=x,y=y,label=label),size=2,angle=90,hjust=1) +
  geom_text(data=data.frame(x=ncol(mdPattern)+1,y=nrow(mdPattern):1,label=missValsPerPattern,z=NA),mapping=aes(x=x,y=y,label=label),size=1.75,angle=0,hjust=0) +
  geom_text(data=data.frame(x=0,y=nrow(mdPattern):1,label=rownames(mdPattern),z=NA),mapping=aes(x=x,y=y,label=label),size=1.75,angle=0,hjust=1) +
  scale_fill_manual(values=c("salmon","steelblue")) +
  guides() +
  theme_void() +
  theme(plot.margin = unit(c(10, 6, 2, 6), "pt")) +
  labs(caption="Missing value patterns in the data. Each column represents one variable.\nThe top annotation states the variable name.\nThe right-hand number indicates the number of missing variables per pattern.\nThe bottom number indicates the proportion of missing data per variable.\nThe left-hand side number indicates the frequency of each pattern in the data.")
# + coord_fixed()

print(g)
Missing data patterns in the RHICCA dataset.

Figure 6.3: Missing data patterns in the RHICCA dataset.

pdf(paste(sep="_",outPrefix,"_missingnessPatterns.pdf"),width=15,height=18)
print(g)
dev.off()

impDat$lims.CD4_Absolute_enrolment[impDat$crf.ptype=="Control"]<-0
impDat$lims.CD4_Absolute_6months[impDat$crf.ptype=="Control"]<-0
impDat$lims.CD4_Absolute_12months[impDat$crf.ptype=="Control"]<-0
impDat$lims.CD4_Absolute_24months[impDat$crf.ptype=="Control"]<-0
impDat$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment[impDat$crf.ptype=="Control"]<-1

impDatLong<-impDat %>%
  dplyr::select(!any_of(c("pwvChange","cimtChange","abpiChange","egfrChange"))) %>%
  pivot_longer(cols=!c(pid,starts_with("crf"),contains("bmi"),contains("waisthip"),lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment,contains("Glucose"),contains("Cholesterol"),lims.CD4_Absolute_enrolment,iris),names_to=c(".value","visit"),names_pattern="([a-zA-z0-9_\\.]+)_(enrolment|[0-9]+months)") %>%
  mutate(visitNum=case_when(
    visit=="enrolment"~0,
    visit=="6months"~6,
    visit=="12months"~12,
    visit=="18months"~18,
    visit=="24months"~24,
    TRUE~NA_real_
  )) %>%
  filter(!is.na(visitNum))

# change from baseline encoding
impDatLong$lims.CD4_Absolute[impDatLong$visitNum==0]<-0
impDatLong$lims.CD4_Absolute[impDatLong$visitNum==6]<-impDatLong$lims.CD4_Absolute[impDatLong$visitNum==6]-impDatLong$lims.CD4_Absolute_enrolment[impDatLong$visitNum==6]
impDatLong$lims.CD4_Absolute[impDatLong$visitNum==12]<-impDatLong$lims.CD4_Absolute[impDatLong$visitNum==12]-impDatLong$lims.CD4_Absolute_enrolment[impDatLong$visitNum==12]
impDatLong$lims.CD4_Absolute[impDatLong$visitNum==18]<-impDatLong$lims.CD4_Absolute[impDatLong$visitNum==18]-impDatLong$lims.CD4_Absolute_enrolment[impDatLong$visitNum==18]
impDatLong$lims.CD4_Absolute[impDatLong$visitNum==24]<-impDatLong$lims.CD4_Absolute[impDatLong$visitNum==24]-impDatLong$lims.CD4_Absolute_enrolment[impDatLong$visitNum==24]

skip.Imp<-TRUE

if(!skip.Imp){
  seed<-202208
  impDat<-impDat %>%
    mutate(
      pwvChange=NA,
      cimtChange=NA,
      abpiChange=NA,
      egfrChange=NA,
      cmvChange=NA,
      vzvChange=NA,
      lims.CD4_Absolute_changeFromBaselineAt24Months=NA,
      lum.CD163_change=NA,
      lum.IL6_change=NA,
      lum.ICAM1_change=NA
    )
  
  impQuickPred <- quickpred(impDat, mincor=0.1, include=c("crf.ptype","crf.age","crf.gender"),exclude=c("pid","iris"))
  meth<-rep("cart",ncol(impDat))
  names(meth)<-colnames(impDat)
  meth["pid"]<-""
  meth["crf.ptype"]<-""
  meth["crf.age"]<-""
  meth["crf.gender"]<-""
  meth["iris"]<-""
  meth[rowSums(impQuickPred)==0]<-""
  meth["pwvChange"]<-"~ I(pwv.pwv_24months - pwv.pwv_enrolment)"
  meth["cimtChange"]<-"~ I(cimt.cimt_24months - cimt.cimt_enrolment)"
  meth["abpiChange"]<-"~ I(abpi.abpi_24months - abpi.abpi_enrolment)"
  meth["egfrChange"]<-"~ I(eGFR_24months - eGFR_enrolment)"
  meth["cmvChange"]<-"~ I(cmv.cmv_6months - cmv.cmv_enrolment)"
  meth["vzvChange"]<-"~ I(vzv.vzv_6months - vzv.vzv_enrolment)"
  meth["lims.CD4_Absolute_changeFromBaselineAt24Months"]<-"~ I(lims.CD4_Absolute_24months-lims.CD4_Absolute_enrolment)"
  meth["lum.CD163_change"]<-"~ I(lum.CD163_6months-lum.CD163_enrolment)"
  meth["lum.IL6_change"]<-"~ I(lum.IL6_6months-lum.IL6_enrolment)"
  meth["lum.ICAM1_change"]<-"~ I(lum.ICAM1_6months-lum.ICAM1_enrolment)"
  
  cat(file=logFile,append=T,"Starting the imputation.\n")
  
  m<-10
  #rhiccaDatWide_impMice <- parlmice(data=impDat, m=m, predictorMatrix=impQuickPred, maxit=5, printFlag=FALSE, n.core=5, n.imp.core=1, cl.type="FORK",method=meth,cluster.seed=seed)
  rhiccaDatWide_impMice <- mice(data=impDat, m=m, predictorMatrix=impQuickPred, maxit=5, printFlag=FALSE, seed=seed, method=meth) # fast enough to not require parallel computations (which get stuck sometimes)
  
  cat(file=logFile,append=T,"Imputation post-processing and saving.\n")
  
  rhiccaDatLong_impMiceStack<-data.frame(impDatLong,.imp=0)
  
  for(i in 1:m){
    tmp<-mice::complete(rhiccaDatWide_impMice,i) %>% select(!any_of(c("pwvChange","cimtChange","abpiChange","egfrChange","cmvChange","vzvChange","lims.CD4_Absolute_changeFromBaselineAt24Months","lum.CD163_change","lum.IL6_change","lum.ICAM1_change")))
    tmpLong<-pivot_longer(tmp,cols=!c(pid,starts_with("crf"),contains("bmi"),contains("waisthip"),lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment,contains("Glucose"),contains("Cholesterol"),lims.CD4_Absolute_enrolment,iris),names_to=c(".value","visit"),names_pattern="([a-zA-z0-9_\\.]+)_(enrolment|[0-9]+months)")
    tmpLong<-tmpLong %>% mutate(visitNum=case_when(
      visit=="enrolment"~0,
      visit=="6months"~6,
      visit=="12months"~12,
      visit=="18months"~18,
      visit=="24months"~24,
    ))
    
    # change from baseline encoding
    tmpLong$lims.CD4_Absolute[tmpLong$visitNum==0]<-0
    tmpLong$lims.CD4_Absolute[tmpLong$visitNum==6]<-tmpLong$lims.CD4_Absolute[tmpLong$visitNum==6]-tmpLong$lims.CD4_Absolute_enrolment[tmpLong$visitNum==6]
    tmpLong$lims.CD4_Absolute[tmpLong$visitNum==12]<-tmpLong$lims.CD4_Absolute[tmpLong$visitNum==12]-tmpLong$lims.CD4_Absolute_enrolment[tmpLong$visitNum==12]
    tmpLong$lims.CD4_Absolute[tmpLong$visitNum==18]<-tmpLong$lims.CD4_Absolute[tmpLong$visitNum==18]-tmpLong$lims.CD4_Absolute_enrolment[tmpLong$visitNum==18]
    tmpLong$lims.CD4_Absolute[tmpLong$visitNum==24]<-tmpLong$lims.CD4_Absolute[tmpLong$visitNum==24]-tmpLong$lims.CD4_Absolute_enrolment[tmpLong$visitNum==24]
    
    rhiccaDatLong_impMiceStack<-rbind(rhiccaDatLong_impMiceStack,data.frame(tmpLong,.imp=i))
  }
  
  rhiccaDatLong_impMiceStack<-rhiccaDatLong_impMiceStack %>%
    mutate(pidLong=paste(sep="_",pid,visit))
  
  rhiccaDatLong_impMice<-as.mids(rhiccaDatLong_impMiceStack,.imp=".imp",.id="pidLong")
  
  save(list=c("impQuickPred","rhiccaDatWide_impMice","rhiccaDatLong_impMice"),file=paste(sep="",outPrefix,"_multiplyImputedData.RData"))
}else{
  date2use<-"20220811"
  prefixTmp<-paste(sep="","../output/",date2use,"/RHICCA_",date2use)
  load(paste(sep="",prefixTmp,"_multiplyImputedData.RData"))
  
  tmpLong<-mice::complete(rhiccaDatWide_impMice, action='long', include=TRUE) %>%
    mutate(
      recruitDate=as.character(obsTime$recruitDate[match(pid,obsTime$pid)]),
      lastVisitDate=as.character(obsTime$lastVisitDate[match(pid,obsTime$pid)]),
      obsTime=as.numeric(obsTime$obsTime[match(pid,obsTime$pid)]),
      eGFR_existingCKD=factor(rhiccaDatWide$eGFR_existingCKD[match(pid,rhiccaDatWide$pid)]),
      cmvStatus=factor(case_when(
        !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "persistently low titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "progression to low titres",
        !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "progression to high titres",
        !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "persistently high titres",
        TRUE~NA_character_
      ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
      vzvStatus=factor(case_when(
        !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "persistently low titres",
        !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "progression to low titres",
        !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "progression to high titres",
        !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "persistently high titres",
        TRUE~NA_character_
      ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
      cmvEnrolmentStatus=factor(case_when(
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment<cmvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment>=cmvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres")),
      vzvEnrolmentStatus=factor(case_when(
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment<vzvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment>=vzvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres"))
    ) %>%
  mutate(
    cmvStatus_2levels=factor(case_when(
      !is.na(cmvStatus) & cmvStatus=="persistently high titres"~"persistently high titres",
      !is.na(cmvStatus) & cmvStatus!="persistently high titres"~"not persistently high titres"
    ),levels=c("not persistently high titres","persistently high titres")),
    vzvStatus_2levels=factor(case_when(
      !is.na(vzvStatus) & vzvStatus=="persistently high titres"~"persistently high titres",
      !is.na(vzvStatus) & vzvStatus!="persistently high titres"~"not persistently high titres"
    ),levels=c("not persistently high titres","persistently high titres"))
  )
  
  rhiccaDatWide_impMice <- as.mids(tmpLong)
}

tmpLong<-mice::complete(rhiccaDatLong_impMice, action='long', include=TRUE) %>%
  mutate(
    lum.CD163_enrolment=tmpLong$lum.CD163_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.CD163_6months=tmpLong$lum.CD163_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.CD163_change=tmpLong$lum.CD163_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))]-tmpLong$lum.CD163_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.IL6_enrolment=tmpLong$lum.IL6_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.IL6_6months=tmpLong$lum.IL6_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.IL6_change=tmpLong$lum.IL6_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))]-tmpLong$lum.IL6_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.ICAM1_enrolment=tmpLong$lum.ICAM1_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.ICAM1_6months=tmpLong$lum.ICAM1_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lum.ICAM1_change=tmpLong$lum.ICAM1_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))]-tmpLong$lum.ICAM1_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    cmv.cmv_enrolment=tmpLong$cmv.cmv_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    cmv.cmv_6months=tmpLong$cmv.cmv_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    cmvChange=tmpLong$cmvChange[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    vzv.vzv_enrolment=tmpLong$vzv.vzv_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    vzv.vzv_6months=tmpLong$vzv.vzv_6months[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    vzvChange=tmpLong$vzvChange[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lims.Glucose_enrolment=tmpLong$lims.Glucose_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    lims.Cholesterol_enrolment=tmpLong$lims.Cholesterol_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))],
    physio.bmi_enrolment=tmpLong$physio.bmi_enrolment[match(paste(sep="_",pid,.imp),paste(sep="_",tmpLong$pid,tmpLong$.imp))]
  ) %>%
  mutate(
    crf.smoke=rhiccaDatWide$crf.smoke[match(pid,rhiccaDatWide$pid)],
    crf.alcohol=rhiccaDatWide$crf.alcohol[match(pid,rhiccaDatWide$pid)],
    eGFR_existingCKD=rhiccaDatWide$eGFR_existingCKD[match(pid,rhiccaDatWide$pid)]
  ) %>%
  mutate(
    cmvStatus=factor(case_when(
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "persistently low titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months<cmvQuartiles["75%"] ~ "progression to low titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment<cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "progression to high titres",
      !is.na(cmv.cmv_enrolment) & !is.na(cmv.cmv_6months) & cmv.cmv_enrolment>=cmvQuartiles["75%"] & cmv.cmv_6months>=cmvQuartiles["75%"] ~ "persistently high titres",
      TRUE~NA_character_
    ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
    vzvStatus=factor(case_when(
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "persistently low titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months<vzvQuartiles["75%"] ~ "progression to low titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment<vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "progression to high titres",
      !is.na(vzv.vzv_enrolment) & !is.na(vzv.vzv_6months) & vzv.vzv_enrolment>=vzvQuartiles["75%"] & vzv.vzv_6months>=vzvQuartiles["75%"] ~ "persistently high titres",
      TRUE~NA_character_
    ),levels=c("persistently low titres","progression to low titres","progression to high titres","persistently high titres")),
    cmvEnrolmentStatus=factor(case_when(
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment<cmvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(cmv.cmv_enrolment) & cmv.cmv_enrolment>=cmvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres")),
      vzvEnrolmentStatus=factor(case_when(
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment<vzvQuartiles["75%"] ~ "low / medium enrolment titres",
      !is.na(vzv.vzv_enrolment) & vzv.vzv_enrolment>=vzvQuartiles["75%"] ~ "high enrolment titres",
      TRUE~NA_character_
    ),levels=c("low / medium enrolment titres","high enrolment titres"))
  ) %>%
  mutate(
    cmvStatus_2levels=factor(case_when(
      !is.na(cmvStatus) & cmvStatus=="persistently high titres"~"persistently high titres",
      !is.na(cmvStatus) & cmvStatus!="persistently high titres"~"not persistently high titres"
    ),levels=c("not persistently high titres","persistently high titres")),
    vzvStatus_2levels=factor(case_when(
      !is.na(vzvStatus) & vzvStatus=="persistently high titres"~"persistently high titres",
      !is.na(vzvStatus) & vzvStatus!="persistently high titres"~"not persistently high titres"
    ),levels=c("not persistently high titres","persistently high titres"))
  )

tmpLong<-tmpLong %>%
  dplyr::mutate(crf.artRegimen.2levels=art$artSimple2Level[match(tmpLong$pid,art$pid)])

rhiccaDatLong_impMice <- as.mids(tmpLong)

tmpLong<-complete(rhiccaDatWide_impMice,action="long",include=TRUE)
tmpLong<-tmpLong %>%
  dplyr::mutate(crf.artRegimen.2levels=art$artSimple2Level[match(tmpLong$pid,art$pid)]) %>%
  dplyr::mutate(
    crf.smoke=rhiccaDatWide$crf.smoke[match(pid,rhiccaDatWide$pid)],
    crf.alcohol=rhiccaDatWide$crf.alcohol[match(pid,rhiccaDatWide$pid)]
  )
rhiccaDatWide_impMice<-as.mids(tmpLong)

7 Baseline population have a low cardiovascular risk profile.

7.0.1 Modifiable CVD risk factors and inflammatory and viral markers over time

We can summarise modifiable CVD risk factors over time by plotting their sample means and 95% confidence intervals over time and by participant type, see Figure 7.1. This shows a low cardiovascular risk for both PLWH and controls at baseline.

# bmi, waist-to-hip, diastolic bp, systolic bp, cholesterol, glucose, eGFR
datTmp<-rhiccaDatLong %>%
  dplyr::select(visitNum,crf.ptype,crf.PLWH,physio.bmi,physio.waisthip,physio.bp_dia,physio.bp_sys,lims.Cholesterol,lims.Glucose,eGFR,cmv.cmv,vzv.vzv,lum.CD163,lum.ICAM1,lum.IL6,lims.CD4_Absolute,lims.HIV_Abbott_Viral_Load_0pt2ml_P) %>%
  filter(!is.na(crf.ptype) & (is.na(lims.Cholesterol) | lims.Cholesterol<2000)) %>%
  group_by(crf.PLWH,visitNum) %>%
  summarise(bmiN=sum(!is.na(physio.bmi)),
            bmiMean=mean(physio.bmi,na.rm=T),
            bmiSD=sd(physio.bmi,na.rm=T),
            bmiMedian=median(physio.bmi,na.rm=T),
            bmi25=quantile(physio.bmi,probs=0.25,na.rm=T),
            bmi75=quantile(physio.bmi,probs=0.75,na.rm=T),
            whrN=sum(!is.na(physio.waisthip)),
            whrMean=mean(physio.waisthip,na.rm=T),
            whrSD=sd(physio.waisthip,na.rm=T),
            whrMedian=median(physio.waisthip,na.rm=T),
            whr25=quantile(physio.waisthip,probs=0.25,na.rm=T),
            whr75=quantile(physio.waisthip,probs=0.75,na.rm=T),
            bpDiaN=sum(!is.na(physio.bp_dia)),
            bpDiaMean=mean(physio.bp_dia,na.rm=T),
            bpDiaSD=sd(physio.bp_dia,na.rm=T),
            bpDiaMedian=median(physio.bp_dia,na.rm=T),
            bpDia25=quantile(physio.bp_dia,probs=0.25,na.rm=T),
            bpDia75=quantile(physio.bp_dia,probs=0.75,na.rm=T),
            bpSysN=sum(!is.na(physio.bp_sys)),
            bpSysMean=mean(physio.bp_sys,na.rm=T),
            bpSysSD=sd(physio.bp_sys,na.rm=T),
            bpSysMedian=median(physio.bp_sys,na.rm=T),
            bpSys25=quantile(physio.bp_sys,probs=0.25,na.rm=T),
            bpSys75=quantile(physio.bp_sys,probs=0.75,na.rm=T),
            cholN=sum(!is.na(lims.Cholesterol)),
            cholMean=mean(lims.Cholesterol,na.rm=T),
            cholSD=sd(lims.Cholesterol,na.rm=T),
            cholMedian=median(lims.Cholesterol,na.rm=T),
            chol25=quantile(lims.Cholesterol,probs=0.25,na.rm=T),
            chol75=quantile(lims.Cholesterol,probs=0.75,na.rm=T),
            glucN=sum(!is.na(lims.Glucose)),
            glucMean=mean(lims.Glucose,na.rm=T),
            glucSD=sd(lims.Glucose,na.rm=T),
            glucMedian=median(lims.Glucose,na.rm=T),
            gluc25=quantile(lims.Glucose,probs=0.25,na.rm=T),
            gluc75=quantile(lims.Glucose,probs=0.75,na.rm=T),
            egfrN=sum(!is.na(eGFR)),
            egfrMean=mean(eGFR,na.rm=T),
            egfrSD=sd(eGFR,na.rm=T),
            egfrMedian=median(eGFR,na.rm=T),
            egfr25=quantile(eGFR,probs=0.25,na.rm=T),
            egfr75=quantile(eGFR,probs=0.75,na.rm=T),
            cmvN=sum(!is.na(cmv.cmv)),
            cmvMean=mean(cmv.cmv,na.rm=T),
            cmvSD=sd(cmv.cmv,na.rm=T),
            cmvMedian=median(cmv.cmv,na.rm=T),
            cmv25=quantile(cmv.cmv,probs=0.25,na.rm=T),
            cmv75=quantile(cmv.cmv,probs=0.75,na.rm=T),
            vzvN=sum(!is.na(vzv.vzv)),
            vzvMean=mean(vzv.vzv,na.rm=T),
            vzvSD=sd(vzv.vzv,na.rm=T),
            vzvMedian=median(vzv.vzv,na.rm=T),
            vzv25=quantile(vzv.vzv,probs=0.25,na.rm=T),
            vzv75=quantile(vzv.vzv,probs=0.75,na.rm=T),
            cd163N=sum(!is.na(lum.CD163)),
            cd163Mean=mean(lum.CD163,na.rm=T),
            cd163SD=sd(lum.CD163,na.rm=T),
            cd163Median=median(lum.CD163,na.rm=T),
            cd16325=quantile(lum.CD163,probs=0.25,na.rm=T),
            cd16375=quantile(lum.CD163,probs=0.75,na.rm=T),
            icam1N=sum(!is.na(lum.ICAM1)),
            icam1Mean=mean(lum.ICAM1,na.rm=T),
            icam1SD=sd(lum.ICAM1,na.rm=T),
            icam1Median=median(lum.ICAM1,na.rm=T),
            icam125=quantile(lum.ICAM1,probs=0.25,na.rm=T),
            icam175=quantile(lum.ICAM1,probs=0.75,na.rm=T),
            il6N=sum(!is.na(lum.IL6)),
            il6Mean=mean(lum.IL6,na.rm=T),
            il6SD=sd(lum.IL6,na.rm=T),
            il6Median=median(lum.IL6,na.rm=T),
            il625=quantile(lum.IL6,probs=0.25,na.rm=T),
            il675=quantile(lum.IL6,probs=0.75,na.rm=T),
            cd4N=sum(!is.na(lims.CD4_Absolute)),
            cd4Mean=mean(lims.CD4_Absolute,na.rm=T),
            cd4SD=sd(lims.CD4_Absolute,na.rm=T),
            cd4Median=median(lims.CD4_Absolute,na.rm=T),
            cd425=quantile(lims.CD4_Absolute,probs=0.25,na.rm=T),
            cd475=quantile(lims.CD4_Absolute,probs=0.75,na.rm=T),
            vlN=sum(!is.na(lims.HIV_Abbott_Viral_Load_0pt2ml_P)),
            vlMean=mean(lims.HIV_Abbott_Viral_Load_0pt2ml_P,na.rm=T),
            vlSD=sd(lims.HIV_Abbott_Viral_Load_0pt2ml_P,na.rm=T),
            vlMedian=median(lims.HIV_Abbott_Viral_Load_0pt2ml_P,na.rm=T),
            vl25=quantile(lims.HIV_Abbott_Viral_Load_0pt2ml_P,probs=0.25,na.rm=T),
            vl75=quantile(lims.HIV_Abbott_Viral_Load_0pt2ml_P,probs=0.75,na.rm=T),
            .groups="drop") %>%
  pivot_longer(cols=c(bmiN,bmiMean,bmiSD,bmiMedian,bmi25,bmi75,
                      whrN,whrMean,whrSD,whrMedian,whr25,whr75,
                      bpDiaN,bpDiaMean,bpDiaSD,bpDiaMedian,bpDia25,bpDia75,
                      bpSysN,bpSysMean,bpSysSD,bpSysMedian,bpSys25,bpSys75,
                      cholN,cholMean,cholSD,cholMedian,chol25,chol75,
                      glucN,glucMean,glucSD,glucMedian,gluc25,gluc75,
                      egfrN,egfrMean,egfrSD,egfrMedian,egfr25,egfr75,
                      cmvN,cmvMean,cmvSD,cmvMedian,cmv25,cmv75,
                      vzvN,vzvMean,vzvSD,vzvMedian,vzv25,vzv75,
                      cd163N,cd163Mean,cd163SD,cd163Median,cd16325,cd16375,
                      icam1N,icam1Mean,icam1SD,icam1Median,icam125,icam175,
                      il6N,il6Mean,il6SD,il6Median,il625,il675,
                      cd4N,cd4Mean,cd4SD,cd4Median,cd425,cd475,
                      vlN,vlMean,vlSD,vlMedian,vl25,vl75),
               names_to="var",
               values_to="value")

datTmpN<-datTmp %>%
  filter(grepl(var,pattern="N")) %>%
  mutate(var=gsub(var,pattern="N",replacement=""))

datTmpMean<-datTmp %>%
  filter(grepl(var,pattern="Mean")) %>%
  mutate(var=gsub(var,pattern="Mean",replacement=""))

datTmpSd<-datTmp %>%
  filter(grepl(var,pattern="SD")) %>%
  mutate(var=gsub(var,pattern="SD",replacement=""))

datTmpMedian<-datTmp %>%
  filter(grepl(var,pattern="Median")) %>%
  mutate(var=gsub(var,pattern="Median",replacement=""))

datTmp25<-datTmp %>%
  filter(grepl(var,pattern="25")) %>%
  mutate(var=gsub(var,pattern="25",replacement=""))

datTmp75<-datTmp %>%
  filter(grepl(var,pattern="75")) %>%
  mutate(var=gsub(var,pattern="75",replacement=""))

datTmp<-left_join(by=c("crf.PLWH","visitNum","var"),datTmpN,datTmpMean,suffix=c(".n",".mean"))
datTmp<-left_join(by=c("crf.PLWH","visitNum","var"),datTmp,datTmpSd,suffix=c("",".sd"))
datTmp<-left_join(by=c("crf.PLWH","visitNum","var"),datTmp,datTmpMedian,suffix=c("",".median"))
datTmp<-left_join(by=c("crf.PLWH","visitNum","var"),datTmp,datTmp25,suffix=c("",".25"))
datTmp<-left_join(by=c("crf.PLWH","visitNum","var"),datTmp,datTmp75,suffix=c("",".75"))

datTmp<-datTmp %>%
  mutate(var=case_when(
    var=="bmi"~"BMI",
    var=="bpDia"~"Bp diastolic",
    var=="bpSys"~"Bp systolic",
    var=="chol"~"Cholesterol",
    var=="egfr"~"eGFR",
    var=="gluc"~"Glucose",
    var=="whr"~"Waist-to-hip ratio",
    var=="cmv"~"CMV",
    var=="vzv"~"VZV",
    var=="cd163"~"CD163",
    var=="icam1"~"ICAM-1",
    var=="il6"~"IL-6",
    var=="cd4"~"CD4+",
    var=="vl"~"HIV viral load",
  ))

colnames(datTmp)<-c("crf.PLWH","visitNum","var","n","mean","sd","median","q25","q75")

datTmp[datTmp$var=="CD4+" & datTmp$crf.PLWH=="Control",4]<-0
datTmp[datTmp$var=="CD4+" & datTmp$crf.PLWH=="Control",5:9]<-NA
datTmp[datTmp$var=="HIV viral load" & datTmp$crf.PLWH=="Control",4]<-0
datTmp[datTmp$var=="HIV viral load" & datTmp$crf.PLWH=="Control",5:9]<-NA

facet_labels <- c("A.  CD4+","B.  HIV viral load","C.  BMI","D.  CMV","E.  Waist-to-hip ratio","F.  VZV","G.  Bp diastolic","H.  CD163","I.  Bp systolic","J.  ICAM-1","K.  Cholesterol","L.  IL-6","M.  Glucose")
names(facet_labels) <- c("CD4+","HIV viral load","BMI","CMV","Waist-to-hip ratio","VZV","Bp diastolic","CD163","Bp systolic","ICAM-1","Cholesterol","IL-6","Glucose")

datTmp$var<-factor(datTmp$var,levels=c("CD4+","HIV viral load","BMI","CMV","Waist-to-hip ratio","VZV","Bp diastolic","CD163","Bp systolic","ICAM-1","Cholesterol","IL-6","Glucose"))

ggModRiskFactors<-datTmp %>%
  #dplyr::filter(var!="CD4+" & var!="HIV viral load") %>%
  dplyr::filter(var!="eGFR" & n!=0 & visitNum<=24) %>%
  dplyr::filter(!(var=="CMV" & visitNum>6)) %>%
  dplyr::filter(!(var=="VZV" & visitNum>6)) %>%
  ggplot(mapping=aes(x=visitNum,y=mean,ymin=mean-1.96*sd/sqrt(n),ymax=mean+1.96*sd/sqrt(n),col=crf.PLWH,fill=crf.PLWH)) +
  #ggplot(mapping=aes(x=visitNum,y=median,ymin=q25,ymax=q75,col=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=2) +
  geom_line(lwd=1,na.rm=T) +
  geom_ribbon(alpha=0.25,linetype=0,na.rm=T) +
  scale_color_manual(values=c("steelblue","orange"),name="") +
  scale_fill_manual(values=c("steelblue","orange"),name="") +
  guides(fill="none",lty="none",pch="none") +
  theme(
    text=element_text(size=16),
    legend.position = "bottom",
    strip.text.x = element_text(hjust = 0, margin=margin(l=0))
  ) +
  xlab("Study visit (months since enrolment)") +
  ylab("") +
  xlim(c(0,24)) +
  facet_wrap(~var,labeller = labeller(var = facet_labels),scales="free_y",nrow=7,ncol=2)

print(ggModRiskFactors)
Modifiable CVD risk factors over time and by participant type.

Figure 7.1: Modifiable CVD risk factors over time and by participant type.

pdf(width=12,height=12,file=paste(sep="_",outPrefix,"CIMT_CVDevents.pdf"))
print(ggModRiskFactors)
dev.off()
## quartz_off_screen 
##                 2

In PLWH we see appropriate viral suppression and immune restoration within 6 months of initiating ART (top 2 panels of Figure 7.1. Therefore, it raises the question of other factors potentially driving CVD events.

8 Risk of asymptomatic CVD: surrogate markers CIMT and PWV

We can summarise both CIMT and PWV progression over the study period in both PLWH and controls and we can fit regression models to interrogate associations with HIV status and other CVD risk factors.

A key finding, for asymptomatic CVD, we saw a bigger increased risk over time with CIMT in PLWH compared to controls (Table 8.1) but did not observe a similar trend for PWV (Table 8.9). We note that this association disappears in the adjusted model.

We also saw a trend toward associations with CMV reactivation and persistently elevated VZV (pVZV) in unadjusted models , Table 8.1, raising the question whether pVZV may play a role. In the adjusted models for PLWH only, the pVZV association becomes statistically significant.

8.1 Carotid intima-media thickness (CIMT)

Our data show that CIMT on average increased between baseline and 24 months. Further, our data show that there is evidence for a weak association between participant type (PLWH or control) and change-from-baseline CIMT with PLWH having on average a larger increase in CIMT over the study period. This association is lost after adjusting for cardiovascular risk factors.

Below we tabulate the average relative increase in CIMT from baseline to 24 month by participant type.

rhiccaDatWide %>% group_by(crf.ptype) %>%
  summarise(baselineCIMT=mean(na.rm=TRUE,(cimt.cimt_24months-cimt.cimt_enrolment)/cimt.cimt_enrolment),.groups="drop")
## # A tibble: 2 × 2
##   crf.ptype baselineCIMT
##   <fct>            <dbl>
## 1 Control         0.0348
## 2 Patient         0.0645

8.1.1 Descriptive summaries

Figures 8.1, 8.2, 8.3, 8.4 and 8.5 summarise the distribution of CIMT between participant types at the different timepoints. Note that the large CIMT values (~2.0) are observed at unscheduled visits for two specific participants: RE10453, RE1096I.

tmpDatAll <- rhiccaDatLong %>%
  dplyr::select(pid,crf.PLWH,physio.bmi_cat_enrolment,physio.hypertension_cat_enrolment,visit,pwv.pwv,cimt.cimt,abpi.abpi,eGFR,lims.CD4_Absolute) %>%
  filter(!is.na(crf.PLWH) & is.element(visit,set=c("enrolment","6months","12months","18months","24months","30months","36months"))) %>%
  group_by(visit,crf.PLWH) %>%
  summarise(
    pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
    cimtMean=mean(cimt.cimt,na.rm=T),cimtSE=sd(cimt.cimt,na.rm=T)/sqrt(sum(!is.na(cimt.cimt))),
    abpiMean=mean(abpi.abpi,na.rm=T),abpiSE=sd(abpi.abpi,na.rm=T)/sqrt(sum(!is.na(abpi.abpi))),
    egfrMean=mean(eGFR,na.rm=T),egfrSE=sd(eGFR,na.rm=T)/sqrt(sum(!is.na(eGFR))),
    cd4Mean=mean(lims.CD4_Absolute,na.rm=T),cd4SE=sd(lims.CD4_Absolute,na.rm=T)/sqrt(sum(!is.na(lims.CD4_Absolute))),
            .groups="drop") %>%
  filter(visit!="unscheduled") %>%
  mutate(visitNum=ifelse(visit=="enrolment",0,as.integer(gsub(pattern="months",replacement="",visit))))

tmpDatBmi <- rhiccaDatLong %>%
  dplyr::select(pid,crf.PLWH,physio.bmi_cat_enrolment,physio.hypertension_cat_enrolment,visit,pwv.pwv,cimt.cimt,abpi.abpi,eGFR,lims.CD4_Absolute) %>%
  filter(!is.na(crf.PLWH) & is.element(visit,set=c("enrolment","6months","12months","18months","24months","30months","36months"))) %>%
  group_by(visit,crf.PLWH,physio.bmi_cat_enrolment) %>%
  summarise(
    pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
    cimtMean=mean(cimt.cimt,na.rm=T),cimtSE=sd(cimt.cimt,na.rm=T)/sqrt(sum(!is.na(cimt.cimt))),
    abpiMean=mean(abpi.abpi,na.rm=T),abpiSE=sd(abpi.abpi,na.rm=T)/sqrt(sum(!is.na(abpi.abpi))),
    egfrMean=mean(eGFR,na.rm=T),egfrSE=sd(eGFR,na.rm=T)/sqrt(sum(!is.na(eGFR))),
    cd4Mean=mean(lims.CD4_Absolute,na.rm=T),cd4SE=sd(lims.CD4_Absolute,na.rm=T)/sqrt(sum(!is.na(lims.CD4_Absolute))),
            .groups="drop") %>%
  filter(visit!="unscheduled") %>%
  mutate(visitNum=ifelse(visit=="enrolment",0,as.integer(gsub(pattern="months",replacement="",visit))))

tmpDatHyper <- rhiccaDatLong %>%
  dplyr::select(pid,crf.PLWH,physio.bmi_cat_enrolment,physio.hypertension_cat_enrolment,visit,pwv.pwv,cimt.cimt,abpi.abpi,eGFR,lims.CD4_Absolute) %>%
  filter(!is.na(crf.PLWH) & is.element(visit,set=c("enrolment","6months","12months","18months","24months","30months","36months"))) %>%
  group_by(visit,crf.PLWH,physio.hypertension_cat_enrolment) %>%
  summarise(
    pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
    cimtMean=mean(cimt.cimt,na.rm=T),cimtSE=sd(cimt.cimt,na.rm=T)/sqrt(sum(!is.na(cimt.cimt))),
    abpiMean=mean(abpi.abpi,na.rm=T),abpiSE=sd(abpi.abpi,na.rm=T)/sqrt(sum(!is.na(abpi.abpi))),
    egfrMean=mean(eGFR,na.rm=T),egfrSE=sd(eGFR,na.rm=T)/sqrt(sum(!is.na(eGFR))),
    cd4Mean=mean(lims.CD4_Absolute,na.rm=T),cd4SE=sd(lims.CD4_Absolute,na.rm=T)/sqrt(sum(!is.na(lims.CD4_Absolute))),
            .groups="drop") %>%
  filter(visit!="unscheduled") %>%
  mutate(visitNum=ifelse(visit=="enrolment",0,as.integer(gsub(pattern="months",replacement="",visit))))
rhiccaDatLong %>%
  as.data.frame() %>%
  filter(!is.na(crf.PLWH)) %>%
  histFun(var="cimt.cimt",groupVar="crf.PLWH",yLab="CIMT (mm)",labels=c("Control","PLWH"),title="CIMT (all visits)")
Histogram of CIMT values across all visits, overall and by participant type.

Figure 8.1: Histogram of CIMT values across all visits, overall and by participant type.

g1<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="cimt.cimt_enrolment",groupVar="crf.PLWH",yLab="CIMT (mm)",labels=c("Control","PLWH"),ylim=c(0.25,1.15),title="CIMT at baseline")

g24<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="cimt.cimt_24months",groupVar="crf.PLWH",yLab="CIMT (mm)",labels=c("Control","PLWH"),ylim=c(0.25,1.15),title="CIMT at 24 months")

grid.arrange(g1,g24,nrow=1)
Violin plots of CIMT measurements at baseline and 24 months.

Figure 8.2: Violin plots of CIMT measurements at baseline and 24 months.

tmpDatAllAdj<-rhiccaDatLong %>%
  filter(visitNum==0 | visitNum==24) %>%
  dplyr::select(pid,visitNum,crf.PLWH,pwv.pwv,cimt.cimt,physio.bmi_cat_enrolment,physio.hypertension_cat_enrolment) %>%
  mutate(
    physio.bmi_enrolment=rhiccaDatWide$physio.bmi_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.bp_dia_enrolment=rhiccaDatWide$physio.bp_dia_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.bp_sys_enrolment=rhiccaDatWide$physio.bp_sys_enrolment[match(pid,rhiccaDatWide$pid)],
    lims.Glucose_enrolment=rhiccaDatWide$lims.Glucose_enrolment[match(pid,rhiccaDatWide$pid)],
    lims.Cholesterol_enrolment=rhiccaDatWide$lims.Cholesterol_enrolment[match(pid,rhiccaDatWide$pid)]
  ) %>%
  filter(rowSums(is.na(.))==0)
tmpDatAllAdj<-tmpDatAllAdj[order(tmpDatAllAdj$pid),]

geeModCimt<-geeglm(cimt.cimt~physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment,data=tmpDatAllAdj,id=factor(tmpDatAllAdj$pid),corstr="exchangeable")

tmpDatAllAdj<-tmpDatAllAdj %>%
  mutate(
    cimt.geeResid=residuals(geeModCimt)
  ) %>%
  group_by(visitNum,crf.PLWH) %>%
  summarise(pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
            cimtMean=mean(cimt.cimt,na.rm=T),cimtSE=sd(cimt.cimt,na.rm=T)/sqrt(sum(!is.na(cimt.cimt))),
            cimtAdjMean=mean(cimt.geeResid,na.rm=T),cimtAdjSE=sd(cimt.geeResid,na.rm=T)/sqrt(sum(!is.na(cimt.geeResid))),
            .groups="drop") 

gCIMT<-tmpDatAll %>%
  filter(visitNum==0 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=cimtMean,ymin=cimtMean-1.96*cimtSE,ymax=cimtMean+1.96*cimtSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("CIMT mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("CIMT (mm)") +
  xlim(c(0,24))

gCIMTAdj<-tmpDatAllAdj %>%
  filter(visitNum==0 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=cimtAdjMean,ymin=cimtAdjMean-1.96*cimtAdjSE,ymax=cimtAdjMean+1.96*cimtAdjSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("Adjusted CIMT mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("Residual CIMT (mm)") +
  labs(caption="Longitudinal CIMT has been adjusted for baseline CVD risk factors\n(waist-hip ratio, systolic and diastolic blood pressure, glucose, cholesterol)\nusing a GEE model with exchangeable correlation structure.") +
  xlim(c(0,24))
  
gCIMTAdj.notitle<-tmpDatAllAdj %>%
  filter(visitNum==0 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=cimtAdjMean,ymin=cimtAdjMean-1.96*cimtAdjSE,ymax=cimtAdjMean+1.96*cimtAdjSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none",col="none") +
  theme(text=element_text(size=12),legend.position="left") +
  xlab("Study visit (months since enrolment)") +
  ylab("Residual CIMT (mm)") +
  #labs(caption="Longitudinal CIMT has been adjusted for baseline CVD risk factors\n(waist-hip ratio, systolic and diastolic blood pressure, glucose, cholesterol)\nusing a GEE model with exchangeable correlation structure.") +
  xlim(c(0,24))
  
grid.arrange(gCIMT,gCIMTAdj,nrow=1)
Raw and adjusted CIMT values observed over time, summarised as sample means and 95% confidence levels.

Figure 8.3: Raw and adjusted CIMT values observed over time, summarised as sample means and 95% confidence levels.

gCIMTbmi<-tmpDatBmi %>%
  filter(visitNum==0 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=cimtMean,ymin=cimtMean-1.96*cimtSE,ymax=cimtMean+1.96*cimtSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("CIMT mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("CIMT (mm)") +
  xlim(c(0,24)) + 
  facet_wrap(~factor(physio.bmi_cat_enrolment,levels=c("underweight","normal","overweight","obese")),nrow = 2)

print(gCIMTbmi)
CIMT values, summarised by sample means and 95% confidence intervals, over time, by participant type and BMI group.

Figure 8.4: CIMT values, summarised by sample means and 95% confidence intervals, over time, by participant type and BMI group.

gCIMThyper<-tmpDatHyper %>%
  filter(visitNum==0 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=cimtMean,ymin=cimtMean-1.96*cimtSE,ymax=cimtMean+1.96*cimtSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("CIMT mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("CIMT (mm)") +
  xlim(c(0,24)) + 
  facet_wrap(~physio.hypertension_cat_enrolment,nrow = 1)

print(gCIMThyper)
CIMT values, summarised by sample means and 95% confidence intervals, over time, by participant type and hypertension group.

Figure 8.5: CIMT values, summarised by sample means and 95% confidence intervals, over time, by participant type and hypertension group.

8.1.2 Regression models

CIMT is only measured at baseline and 24 months. For this reason, simple GLM models are fitted for CIMT. We use standard linear regression models for a change-from-baseline analysis (change-from-baseline CIMT is the response variable).

As for PWV, we fit 3 models: unadjusted model for all participants, adjusted model for all participants and an adjusted model for PLWH only. Baseline CIMT measurements are included as a predictor in all models as is recommended practice.

In the first model, the unadjusted model, we observe a statistically significant difference between PLWH and controls.

tmpLong<-mice::complete(rhiccaDatWide_impMice, action='long', include=TRUE) %>%
  dplyr::mutate(
      cmv.cmv_CFB=cmv.cmv_6months-cmv.cmv_enrolment,
      vzv.vzv_CFB=vzv.vzv_6months-vzv.vzv_enrolment
    )
rhiccaDatWide_impMice <- as.mids(tmpLong)


tmpDatWide<-rhiccaDatWide %>%
  mutate(
    pwvChange=pwv.pwv_24months-pwv.pwv_enrolment,
    cimtChange=cimt.cimt_24months-cimt.cimt_enrolment,
    abpiChange=abpi.abpi_24months-abpi.abpi_enrolment,
    egfrChange=eGFR_24months-eGFR_enrolment
  )

obj1GlmCimt.ptype<-glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment,data=tmpDatWide) # another marker of vasculopathy; unadjusted model

obj1GlmCimt.baseline.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~cimt.cimt_enrolment))
obj1GlmCimt.ptype.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~crf.ptype+cimt.cimt_enrolment))
obj1GlmCimt.sex.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~crf.gender+cimt.cimt_enrolment))
obj1GlmCimt.age.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~crf.age+cimt.cimt_enrolment))
obj1GlmCimt.waisthip.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~physio.waisthip_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.bmi.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~physio.bmi_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.diabp.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~physio.bp_dia_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.sysbp.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~physio.bp_sys_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.glucose.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~lims.Glucose_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.cholesterol.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~lims.Cholesterol_enrolment+cimt.cimt_enrolment))
obj1GlmCimt.cmv.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~cmvStatus+cimt.cimt_enrolment))
obj1GlmCimt.vzv.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~vzvStatus+cimt.cimt_enrolment))

obj1GlmCimtAdjGlucChol<-glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment,data=tmpDatWide) # another marker of vasculopathy; unadjusted model
obj1GlmCimtAdjGlucCholInt<-glm(cimtChange~crf.ptype+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment*crf.gender+lims.Cholesterol_enrolment*crf.gender,data=tmpDatWide) # another marker of vasculopathy; unadjusted model

obj1GlmCimtAdjGlucChol.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~crf.ptype+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus)) 
#summary(pool(obj1GlmCimtAdjGlucChol.mid))

obj1GlmCimtAdjGlucChol.quantCmvVzv.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmv.cmv_enrolment+cmv.cmv_CFB+vzv.vzv_enrolment+vzv.vzv_CFB)) # no sig assoc with VZV

obj1GlmCimtAdjCmvVzvOnly.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment+cmvStatus+vzvStatus))

obj1GlmCimtAdjGlucCholSolMarkers.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+lum.ICAM1_enrolment+lum.CD163_enrolment+lum.IL6_enrolment)) 

obj1GlmCimtAdjGlucChol.noPtype.mid<-with(rhiccaDatWide_impMice,glm(cimtChange~cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment)) 

m<-length(obj1GlmCimtAdjGlucChol.mid$analyses)
obj1GlmCimtAdjGlucChol.mid.residuals.list<-list()
obj1GlmCimtAdjCmvVzvOnly.mid.residuals.list<-list()
obj1GlmCimtAdjGlucChol.noPtype.mid.residuals.list<-list()
for(i in 1:m){
  obj1GlmCimtAdjGlucChol.mid.residuals.list[[i]]<-residuals(obj1GlmCimtAdjGlucChol.mid$analyses[[i]])
  obj1GlmCimtAdjCmvVzvOnly.mid.residuals.list[[i]]<-residuals(obj1GlmCimtAdjCmvVzvOnly.mid$analyses[[i]])
  obj1GlmCimtAdjGlucChol.noPtype.mid.residuals.list[[i]]<-residuals(obj1GlmCimtAdjGlucChol.noPtype.mid$analyses[[i]])
  if(i==1){
    obj1GlmCimtAdjGlucChol.mid.residuals<-obj1GlmCimtAdjGlucChol.mid.residuals.list[[i]]/m
    obj1GlmCimtAdjCmvVzvOnly.mid.residuals<-obj1GlmCimtAdjCmvVzvOnly.mid.residuals.list[[i]]/m
    obj1GlmCimtAdjGlucChol.noPtype.mid.residuals<-obj1GlmCimtAdjGlucChol.noPtype.mid.residuals.list[[i]]/m
  }else{
    obj1GlmCimtAdjGlucChol.mid.residuals<-obj1GlmCimtAdjGlucChol.mid.residuals+obj1GlmCimtAdjGlucChol.mid.residuals.list[[i]]/m
    obj1GlmCimtAdjCmvVzvOnly.mid.residuals<-obj1GlmCimtAdjCmvVzvOnly.mid.residuals+obj1GlmCimtAdjCmvVzvOnly.mid.residuals.list[[i]]/m
    obj1GlmCimtAdjGlucChol.noPtype.mid.residuals<-obj1GlmCimtAdjGlucChol.noPtype.mid.residuals+obj1GlmCimtAdjGlucChol.noPtype.mid.residuals.list[[i]]/m
  }
}

tmpDatCimt<-data.frame(
  pid=rhiccaDatWide$pid,
  ptype=rhiccaDatWide$crf.ptype,
  cimtChangeResNoPtype=obj1GlmCimtAdjGlucChol.noPtype.mid.residuals,
  cimtChangeResPtype=obj1GlmCimtAdjGlucChol.mid.residuals,
  cimtChangeResPtypeCmvVzvOnly=obj1GlmCimtAdjCmvVzvOnly.mid.residuals
)

gCimtModAdjResiduals.noPtype<-tmpDatCimt %>%
  ggplot(mapping=aes(x=ptype,y=cimtChangeResNoPtype)) +
  geom_boxplot()

gCimtModAdjResiduals.Ptype<-tmpDatCimt %>%
  ggplot(mapping=aes(x=ptype,y=cimtChangeResPtype)) +
  geom_boxplot()

gCimtModAdjResiduals.PtypeCmvVzvOnly<-tmpDatCimt %>%
  ggplot(mapping=aes(x=ptype,y=cimtChangeResPtypeCmvVzvOnly)) +
  geom_boxplot()

#grid.arrange(gCimtModAdjResiduals.noPtype,gCimtModAdjResiduals.noPtype,nrow=1)

obj1GlmCimtAdjGlucCholSolMarkers<-glm(cimtChange~ifelse(crf.ptype=="Patient",1,0)+cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment*crf.gender+lims.Cholesterol_enrolment*crf.gender+lum.CD163_enrolment+lum.ICAM1_enrolment,data=tmpDatWide) # another marker of vasculopathy; unadjusted model

tmp<-mice::complete(rhiccaDatWide_impMice,1)
subsetHIV<-tmp$crf.ptype=="Patient"
rhiccaDatWide_impMice.hiv<-miceadds::subset_datlist(rhiccaDatWide_impMice,subset=subsetHIV,select=NULL,expr_subset=NULL,index=NULL)
rhiccaDatWide_impMice.hiv<-miceadds::datlist2mids(rhiccaDatWide_impMice.hiv)
tmpLong<-mice::complete(rhiccaDatWide_impMice.hiv, action='long', include=TRUE) %>%
  dplyr::mutate(
      cmv.cmv_CFB=cmv.cmv_6months-cmv.cmv_enrolment,
      vzv.vzv_CFB=vzv.vzv_6months-vzv.vzv_enrolment
    )
rhiccaDatWide_impMice.hiv <- as.mids(tmpLong)

obj1GlmCimtAdjGlucChol.hiv.mid<-with(rhiccaDatWide_impMice.hiv,glm(cimtChange~cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months))
obj1GlmCimtAdjGlucChol.quantCmvVzv.hiv.mid<-with(rhiccaDatWide_impMice.hiv,glm(cimtChange~cimt.cimt_enrolment+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmv.cmv_enrolment+cmv.cmv_CFB+vzv.vzv_enrolment+vzv.vzv_CFB+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months)) # no sig assoc with VZV
obj1GlmCimtAdjCmvVzvOnly.hiv.mid<-with(rhiccaDatWide_impMice.hiv,glm(cimtChange~cimt.cimt_enrolment+cmvStatus+vzvStatus)) 
summary(pool(obj1GlmCimt.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimt.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model CIMT-1: Results for the linear regression model for change from baseline CIMT with participant type and baseline CIMT as predictors. Model fitted to multiply imputed data.",digits=4,row_names=c("Intercept","Participant type: PLWH","Baseline CIMT"),escape=F) %>%
  kable_styling(full_width=F)

In the adjusted model for all participants (adjusted for the same variables as the PWV models, but we use baseline values for all independent variables), this difference is no longer statistically significant. No other covariates have significant effects, though age is borderline above the significance threshold.

summary(pool(obj1GlmCimtAdjGlucChol.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjGlucChol.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model CIMT-2: Results for the linear regression model for change from baseline CIMT with participant type, baseline CIMT and individual-level covariates (at baseline) as predictors. Model fitted to multiply imputed data.",digits=4,row_names=c("Intercept","Participant type: PLWH","Baseline CIMT","Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),escape=F) %>%
  kable_styling(full_width=F)

Likewise, in the PLWH only model, we do not observe any significant effects (age again borderline above the 5% significance threshold). This model also takes into account pre-existing and new onset vasculopathy (IRIS for the latter; we only consider 6 months after ART start). Vasculopathy is defined with respect to PWV (vasculopathy being defined as PWV>12).

summary(pool(obj1GlmCimtAdjGlucChol.hiv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjGlucChol.hiv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model CIMT-3: Results for the linear mixed model for change from baseline CIMT with participant type, baseline CIMT and individual-level covariates (at baseline) as predictors. Model fitted to multiply imputed data.",digits=4,row_names=c("Intercept","Baseline CIMT","Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CD4 (baseline)","CD4 (change from Baseline at 24 months)","log10(viral load)"),escape=F) %>%
  kable_styling(full_width=F)

Table 8.1 shows a combined summary for the 3 CIMT models

#helper functions
sumFitandSum_cimt<-function(varString){
  mod<-with(rhiccaDatWide_impMice,glm(as.formula(paste(sep="","cimtChange~cimt.cimt_enrolment",varString))))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=3,round(digits=3,p.value)),bold=T),cell_spec(format(nsmall=3,round(digits=3,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  return(sumObj)
}

sumFitandSum_cimt.hiv<-function(varString){
  mod<-with(rhiccaDatWide_impMice.hiv,glm(as.formula(paste(sep="","cimtChange~cimt.cimt_enrolment",varString))))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=3,round(digits=3,p.value)),bold=T),cell_spec(format(nsmall=3,round(digits=3,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  return(sumObj)
}

tab1.baseline<-sumFitandSum_cimt("")
tab1.ptype<-sumFitandSum_cimt("+crf.ptype")
tab1.sex<-sumFitandSum_cimt("+crf.gender")
tab1.smoke<-sumFitandSum_cimt("+crf.smoke")
tab1.alcohol<-sumFitandSum_cimt("+crf.alcohol")
tab1.age<-sumFitandSum_cimt("+crf.age")
tab1.waisthip<-sumFitandSum_cimt("+physio.waisthip_enrolment")
tab1.bmi<-sumFitandSum_cimt("+physio.bmi_enrolment")
tab1.diabp<-sumFitandSum_cimt("+physio.bp_dia_enrolment")
tab1.sysbp<-sumFitandSum_cimt("+physio.bp_sys_enrolment")
tab1.glucose<-sumFitandSum_cimt("+lims.Glucose_enrolment")
tab1.cholesterol<-sumFitandSum_cimt("+lims.Cholesterol_enrolment")
tab1.ckd<-sumFitandSum_cimt("+eGFR_existingCKD")
tab1.cmv<-sumFitandSum_cimt("+cmvStatus")
tab1.vzv<-sumFitandSum_cimt("+vzvStatus")

tab1<-rbind(tab1.baseline,
            tab1.ptype,
            tab1.sex,
            tab1.age,
            tab1.smoke,
            tab1.alcohol,
            tab1.waisthip,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            tab1.ckd,
            tab1.cmv,
            tab1.vzv)

tab2<-sumFitandSum_cimt("+crf.ptype+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus")

tab3<-sumFitandSum_cimt.hiv("+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab4.baseline<-sumFitandSum_cimt.hiv("")
tab4.sex<-sumFitandSum_cimt.hiv("+crf.gender")
tab4.age<-sumFitandSum_cimt.hiv("+crf.age")
tab4.smoke<-sumFitandSum_cimt.hiv("+crf.smoke")
tab4.alcohol<-sumFitandSum_cimt.hiv("+crf.alcohol")
tab4.waisthip<-sumFitandSum_cimt.hiv("+physio.waisthip_enrolment")
tab4.bmi<-sumFitandSum_cimt.hiv("+physio.bmi_enrolment")
tab4.diabp<-sumFitandSum_cimt.hiv("+physio.bp_dia_enrolment")
tab4.sysbp<-sumFitandSum_cimt.hiv("+physio.bp_sys_enrolment")
tab4.glucose<-sumFitandSum_cimt.hiv("+lims.Glucose_enrolment")
tab4.cholesterol<-sumFitandSum_cimt.hiv("+lims.Cholesterol_enrolment")
tab4.ckd<-sumFitandSum_cimt.hiv("+eGFR_existingCKD")
tab4.cmv<-sumFitandSum_cimt.hiv("+cmvStatus")
tab4.vzv<-sumFitandSum_cimt.hiv("+vzvStatus")
tab4.cd4base<-sumFitandSum_cimt.hiv("+lims.CD4_Absolute_enrolment")
tab4.cd4change<-sumFitandSum_cimt.hiv("+lims.CD4_Absolute_changeFromBaselineAt24Months")
tab4.vl<-sumFitandSum_cimt.hiv("+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab4<-rbind(tab4.baseline,
            tab4.sex,
            tab4.age,
            tab4.smoke,
            tab4.alcohol,
            tab4.waisthip,
            tab4.bmi,
            tab4.diabp,
            tab4.sysbp,
            tab4.glucose,
            tab4.cholesterol,
            tab4.ckd,
            tab4.cmv,
            tab4.vzv,
            tab4.cd4base,
            tab4.cd4change,
            tab4.vl)

allRows<-setdiff(unique(c(tab1$term,tab2$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA,coefficient.hivadj=NA,SE.hivadj=NA,pvalue.hivadj=NA)

tabAll$coefficient.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$SE.unadj<-tab1$std.error[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$coefficient.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$SE.adj<-tab2$std.error[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tabAll$coefficient.hivadj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.hivadj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.hivadj<-tab3$p.value[match(tabAll$term,tab3$term)]
                              
tab5<-summary(pool(obj1GlmCimtAdjCmvVzvOnly.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjCmvVzvOnly.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term))

tab6<-summary(pool(obj1GlmCimtAdjCmvVzvOnly.hiv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjCmvVzvOnly.hiv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term))

tab7<-summary(pool(obj1GlmCimtAdjGlucChol.quantCmvVzv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjGlucChol.quantCmvVzv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term))

tab8<-summary(pool(obj1GlmCimtAdjGlucChol.quantCmvVzv.hiv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1GlmCimtAdjGlucChol.quantCmvVzv.hiv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term))

tab<-rbind(tab1,tab2,tab3)
tabAlt<-rbind(tab5,tab6)
tabAlt2<-rbind(tab7,tab8)

# rn<-c(
#     c("Intercept","Participant type: PLWH","Baseline CIMT"),
#     c("Intercept ","Participant type: PLWH ","Baseline CIMT ","Sex: male","Age (in years)","Waist-hip ratio","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),
#     c("Intercept  ","Baseline CIMT  ","Sex: male ","Age (in years) ","Waist-hip ratio ","Diastolic blood pressure ","Systolic blood pressure ","Glucose ","Cholesterol ","CMV: progression to latency ","CMV: reactivation ","CMV: persistently high titres ","VZV: progression to latency ","VZV: reactivation ","VZV: persistently high titres ","CD4 (baseline)","CD4 (change from Baseline at 24 months)","log10(viral load)")
#   )

rn<-c("Baseline CIMT","Participant type: PLWH","Sex: male","Age (in years)","Current smoker","Drink alcohol","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from Baseline at 24 months)","log10 viral load (baseline)")

rnAlt<-c(
    c("Intercept ","Participant type: PLWH ","Baseline CIMT ","CMV: progression to low titres ","CMV: progression to high titres ","CMV: persistently high titres ","VZV: progression to low titres ","VZV: progression to high titres ","VZV: persistently high titres "),
    c("Intercept  ","Baseline CIMT  ","CMV: progression to low titres  ","CMV: progression to high titres  ","CMV: persistently high titres  ","VZV: progression to low titres  ","VZV: progression to high titres  ","VZV: persistently high titres  ")
  )

rnAlt2<-c(
    c("Intercept ","Participant type: PLWH ","Baseline CIMT ","Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV (enrolment)","CMV (change from baseline at 6 months)","VZV (enrolment)","VZV (change from baseline at 6 months)"),
    c("Intercept  ","Baseline CIMT  ","Sex: male ","Age (in years) ","BMI ","Diastolic blood pressure ","Systolic blood pressure ","Glucose ","Cholesterol ","CMV (enrolment) ","CMV (change from baseline at 6 months) ","VZV (enrolment) ","VZV (change from baseline at 6 months) ","CD4 (baseline)","CD4 (change from Baseline at 24 months)")
  )

options(knitr.kable.NA = '')

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),3),caption="Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models for all participants, multiple regression model for all participants and multiple regression model for PLWH only.)") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models, all data" = 3, "Multiple regression model, all data" = 3, "Multiple regression model, PLWH" = 3)) %>%
  kable_styling(full_width=F)
Table 8.1: Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models for all participants, multiple regression model for all participants and multiple regression model for PLWH only.)
Unadjusted models, all data
Multiple regression model, all data
Multiple regression model, PLWH
Coefficient SE p Coefficient SE p Coefficient SE p
Baseline CIMT 0.0427 0.0431 0.326 0.0085 0.0558 0.880 0.0558 0.0704 0.432
Participant type: PLWH 0.0164 0.0068 0.017 0.0098 0.0082 0.233
Sex: male 0.0016 0.0059 0.790 -0.0032 0.0068 0.636 -0.0044 0.0086 0.611
Age (in years) 0.0008 0.0006 0.178 0.0008 0.0006 0.179 0.0010 0.0008 0.195
Current smoker -0.0043 0.0087 0.620 -0.0068 0.0105 0.515 -0.0071 0.0122 0.559
Drink alcohol 0.0005 0.0073 0.942 0.0025 0.0088 0.774 0.0026 0.0099 0.795
Waist-hip ratio -0.0387 0.0435 0.374 -0.0434 0.0461 0.347 -0.0416 0.0547 0.447
BMI -0.0010 0.0006 0.092 -0.0001 0.0007 0.886 -0.0006 0.0010 0.548
Diastolic blood pressure -0.0002 0.0002 0.355 -0.0004 0.0005 0.476 -0.0005 0.0006 0.369
Systolic blood pressure -0.0001 0.0001 0.555 0.0002 0.0003 0.494 0.0004 0.0004 0.290
Glucose 0.0002 0.0014 0.898 0.0005 0.0015 0.739 0.0011 0.0018 0.546
Cholesterol -0.0046 0.0027 0.086 -0.0022 0.0030 0.467 -0.0044 0.0037 0.244
Existing CKD -0.0087 0.0136 0.521 -0.0133 0.0138 0.339 -0.0184 0.0168 0.275
CMV: progression to low titres -0.0081 0.0202 0.687 -0.0069 0.0205 0.736 -0.0011 0.0234 0.961
CMV: progression to high titres 0.0179 0.0082 0.030 0.0123 0.0084 0.143 0.0144 0.0098 0.142
CMV: persistently high titres 0.0114 0.0087 0.193 0.0071 0.0088 0.423 0.0074 0.0101 0.461
VZV: progression to low titres 0.0201 0.0097 0.041 0.0182 0.0097 0.062 0.0219 0.0120 0.071
VZV: progression to high titres 0.0049 0.0139 0.725 0.0052 0.0142 0.714 0.0064 0.0158 0.684
VZV: persistently high titres 0.0163 0.0078 0.037 0.0137 0.0079 0.083 0.0187 0.0093 0.046
CD4 (baseline) 0.0000 0.0000 0.592
CD4 (change from Baseline at 24 months) 0.0000 0.0000 0.241
log10 viral load (baseline) 0.0001 0.0029 0.966
write.csv(tabAll,row.names=F,file=paste(sep="_",outPrefix,"CIMT_regressionModels.csv"))

tabAll.cimt<-tabAll

Note that the intercept in the unadjusted model gives the average change in CIMT over 24 months:

sumFitandSum_cimt.hiv("-cimt.cimt_enrolment") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.2: Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to PLWH only.
Coefficient SE p
(Intercept) 0.033 0.003 <0.001

We can also pull this out for the adjusted model:

tab3 %>%
  dplyr::filter(term=="(Intercept)") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.3: Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to PLWH only.
Coefficient SE p
(Intercept) -0.002 0.057 0.971

And we can repeat this for all participants. The intercept in the unadjusted model gives the average change in CIMT over 24 months:

sumFitandSum_cimt("-cimt.cimt_enrolment") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to all participants.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.4: Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to all participants.
Coefficient SE p
(Intercept) 0.03 0.003 <0.001

We can also pull this out for the adjusted model:

tab2 %>%
  dplyr::filter(term=="(Intercept)") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to all participants.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.5: Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to all participants.
Coefficient SE p
(Intercept) 0.025 0.047 0.588
tab4$term<-as.character(tab4$term)
tab3$term<-as.character(tab3$term)
allRows<-setdiff(unique(c(tab4$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA)

tabAll$coefficient.unadj<-tab4$estimate[match(tabAll$term,tab4$term)]
tabAll$SE.unadj<-tab4$std.error[match(tabAll$term,tab4$term)]
tabAll$pvalue.unadj<-tab4$p.value[match(tabAll$term,tab4$term)]

tabAll$coefficient.adj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.adj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.adj<-tab3$p.value[match(tabAll$term,tab3$term)]

rn<-c("Baseline CIMT","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from Baseline at 24 months)","log10 viral load (baseline)")

options(knitr.kable.NA = '')

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),2),caption="Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  kable_styling(full_width=F)
Table 8.6: Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p
Baseline CIMT 0.103 0.054 0.058 0.056 0.070 0.432
Sex: male 0.001 0.007 0.876 -0.004 0.009 0.611
Age (in years) 0.001 0.001 0.133 0.001 0.001 0.195
Current smoker -0.003 0.010 0.742 -0.007 0.012 0.559
Alcohol drinker -0.001 0.009 0.946 0.003 0.010 0.795
Waist-hip ratio -0.031 0.052 0.548 -0.042 0.055 0.447
BMI -0.001 0.001 0.222 -0.001 0.001 0.548
Diastolic blood pressure 0.000 0.000 0.693 -0.001 0.001 0.369
Systolic blood pressure 0.000 0.000 0.875 0.000 0.000 0.290
Glucose 0.001 0.002 0.611 0.001 0.002 0.546
Cholesterol -0.005 0.004 0.205 -0.004 0.004 0.244
Existing CKD -0.014 0.017 0.401 -0.018 0.017 0.275
CMV: progression to low titres -0.008 0.023 0.716 -0.001 0.023 0.961
CMV: progression to high titres 0.017 0.009 0.062 0.014 0.010 0.142
CMV: persistently high titres 0.008 0.010 0.403 0.007 0.010 0.461
VZV: progression to low titres 0.022 0.012 0.061 0.022 0.012 0.071
VZV: progression to high titres 0.004 0.016 0.801 0.006 0.016 0.684
VZV: persistently high titres 0.020 0.009 0.032 0.019 0.009 0.046
CD4 (baseline) 0.000 0.000 0.668 0.000 0.000 0.592
CD4 (change from Baseline at 24 months) 0.000 0.000 0.335 0.000 0.000 0.241
log10 viral load (baseline) 0.001 0.003 0.664 0.000 0.003 0.966
tabAll.cimt.hiv<-tabAll
tabAlt %>%
  kableRn(digits=4,escape=F,row_names=rnAlt,caption="Model summaries for 2 additional models fitted to CIMT as outcome (adjusted model for all participants and PLWH only where adjustment is only for CMV and VZV status.)") %>%
  pack_rows(index = c("Adjusted model, all data" = 9, "Adjusted model, PLWH only" = 8)) %>%
  kable_styling(full_width=F)
Table 8.7: Model summaries for 2 additional models fitted to CIMT as outcome (adjusted model for all participants and PLWH only where adjustment is only for CMV and VZV status.)
estimate std.error statistic df p.value
Adjusted model, all data
Intercept -0.0096 0.0234 -0.4120 69.5976 0.6816
Participant type: PLWH 0.0113 0.0072 1.5655 407.2418 0.1183
Baseline CIMT 0.0456 0.0437 1.0432 57.9606 0.3012
CMV: progression to low titres -0.0090 0.0200 -0.4523 550.4132 0.6512
CMV: progression to high titres 0.0140 0.0084 1.6718 535.8978 0.0952
CMV: persistently high titres 0.0070 0.0089 0.7876 63.5009 0.4338
VZV: progression to low titres 0.0178 0.0096 1.8513 151.1601 0.0661
VZV: progression to high titres 0.0037 0.0141 0.2629 262.2942 0.7928
VZV: persistently high titres 0.0140 0.0078 1.7923 324.8541 0.0740
Adjusted model, PLWH only
Intercept -0.0248 0.0267 -0.9276 93.9517 0.3560
Baseline CIMT 0.0945 0.0539 1.7524 71.6226 0.0840
CMV: progression to low titres -0.0062 0.0225 -0.2746 578.9454 0.7837
CMV: progression to high titres 0.0164 0.0093 1.7724 569.6967 0.0769
CMV: persistently high titres 0.0065 0.0096 0.6762 78.6618 0.5009
VZV: progression to low titres 0.0215 0.0116 1.8470 104.4557 0.0676
VZV: progression to high titres 0.0051 0.0157 0.3233 280.5830 0.7467
VZV: persistently high titres 0.0189 0.0092 2.0634 300.4709 0.0399
tabAlt2 %>%
  kableRn(digits=4,escape=F,row_names=rnAlt2,caption="Model summaries for another 2 additional models fitted to CIMT as outcome (adjusted model for all participants and PLWH only where adjustment is for the continuous CMV and VZV measurements.)") %>%
  pack_rows(index = c("Adjusted model, all data" = 14, "Adjusted model, PLWH only" = 15)) %>%
  kable_styling(full_width=F)
Table 8.8: Model summaries for another 2 additional models fitted to CIMT as outcome (adjusted model for all participants and PLWH only where adjustment is for the continuous CMV and VZV measurements.)
estimate std.error statistic df p.value
Adjusted model, all data
Intercept -0.0064 0.0323 -0.1990 196.7261 0.8425
Participant type: PLWH 0.0105 0.0082 1.2856 267.3073 0.1997
Baseline CIMT 0.0082 0.0559 0.1474 57.9949 0.8833
Sex: male -0.0039 0.0064 -0.6116 290.6100 0.5412
Age (in years) 0.0007 0.0006 1.2439 34.8876 0.2218
BMI -0.0002 0.0007 -0.3189 499.0811 0.7500
Diastolic blood pressure -0.0003 0.0005 -0.6557 378.2575 0.5124
Systolic blood pressure 0.0002 0.0003 0.6019 419.3773 0.5476
Glucose 0.0001 0.0014 0.0944 792.1813 0.9248
Cholesterol -0.0022 0.0030 -0.7437 154.2561 0.4582
CMV (enrolment) 0.0000 0.0000 0.1661 160.6307 0.8683
CMV (change from baseline at 6 months) 0.0000 0.0000 1.3049 286.1586 0.1930
VZV (enrolment) 0.0000 0.0000 1.3838 263.9358 0.1676
VZV (change from baseline at 6 months) 0.0000 0.0000 -0.3461 349.6715 0.7295
Adjusted model, PLWH only
Intercept -0.0358 0.0381 -0.9396 212.3443 0.3485
Baseline CIMT 0.0544 0.0704 0.7728 54.1398 0.4430
Sex: male -0.0049 0.0080 -0.6044 245.0394 0.5461
Age (in years) 0.0010 0.0008 1.2713 29.9475 0.2134
BMI -0.0007 0.0009 -0.7287 236.2229 0.4669
Diastolic blood pressure -0.0005 0.0006 -0.8766 393.4250 0.3813
Systolic blood pressure 0.0004 0.0004 1.0493 508.8965 0.2945
Glucose 0.0007 0.0017 0.4064 516.9907 0.6846
Cholesterol -0.0043 0.0038 -1.1356 137.8255 0.2581
CMV (enrolment) 0.0000 0.0000 0.3024 188.6485 0.7627
CMV (change from baseline at 6 months) 0.0000 0.0000 1.4689 366.1948 0.1427
VZV (enrolment) 0.0000 0.0000 1.4658 199.3832 0.1443
VZV (change from baseline at 6 months) 0.0000 0.0000 -0.2293 256.0582 0.8188
CD4 (baseline) 0.0000 0.0000 0.6676 82.6753 0.5062
CD4 (change from Baseline at 24 months) 0.0000 0.0000 1.1613 92.6416 0.2485

8.2 Pulse Wave Velocity (PWV)

As an executive summary, the RHICCA data do not show that there is an association between PWV over time and participant type. Whilst a weak association with participant type is observed in an unadjusted model (both in terms of overall PWV level and change in PWV over time), this disappears when the model takes other cardiovascular risk factors into account. On average, PWV decreases over the 24 month study period.

8.2.1 Descriptive summaries

Figures 8.6, 8.7, 8.8, 8.9 and 8.10 summarise the distribution of PWV between participant types overall and at the different timepoints.

There is a marked dip in PWV in controls at 18 months and this is consistent: it can be seen overall, across all BMI groups (though perhaps fitting more in with the overall trend over time for overweight and obese) and across all blood pressure groups.

We investigated whether this dip could be due to observer variability. However, it does not seem to be explained by a staff member who would consistently record lower PWV. While 2 of the 3 staff with lowest average PWV measurements across all visits (excluding at 18 months), IS and SN, measured a slightly larger proportion of participants at 18 months (total of 79% compared to 60%), the dip persists when the plot is redone with excluding measurements from these 2 staff (though the dip is less pronounced; figure not shown).

rhiccaDatLong %>%
  as.data.frame() %>%
  filter(!is.na(crf.PLWH)) %>%
  histFun(var="pwv.pwv",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),title="PWV (all visits)")
Histogram of all PWV measurements across all visits, overall and by participant type.

Figure 8.6: Histogram of all PWV measurements across all visits, overall and by participant type.

g1<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_enrolment",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at baseline")

g6<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_6months",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at 6 months")

g12<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_12months",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at 12 months")

g18<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_18months",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at 18 months")

g24<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_24months",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at 24 months")

g30<-rhiccaDatWide %>%
  as.data.frame() %>%
  filter(!is.na(crf.ptype)) %>%
  violinPlotFun(var="pwv.pwv_30months",groupVar="crf.PLWH",yLab="PWV (m/s)",labels=c("Control","PLWH"),ylim=c(3,20),title="PWV at 30 months")

grid.arrange(g1,g6,g12,g18,g24,g30,nrow=2)
Violin plots of PWV measurements at the different visits, stratified by participant type.

Figure 8.7: Violin plots of PWV measurements at the different visits, stratified by participant type.

gPWV<-tmpDatAll %>%
  ggplot(mapping=aes(x=visitNum,y=pwvMean,ymin=pwvMean-1.96*pwvSE,ymax=pwvMean+1.96*pwvSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("PWV mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("PWV (m/s)") +
  xlim(c(0,24))

tmpDatAllAdj<-rhiccaDatLong %>%
  filter(visitNum==0 | visitNum==6 | visitNum==12 | visitNum==18 | visitNum==24) %>%
  dplyr::select(pid,visitNum,crf.PLWH,pwv.pwv,physio.bmi_cat_enrolment,physio.hypertension_cat_enrolment) %>%
  mutate(
    physio.bmi_enrolment=rhiccaDatWide$physio.bmi_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.waisthip_enrolment=rhiccaDatWide$physio.waisthip_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.bp_dia_enrolment=rhiccaDatWide$physio.bp_dia_enrolment[match(pid,rhiccaDatWide$pid)],
    physio.bp_sys_enrolment=rhiccaDatWide$physio.bp_sys_enrolment[match(pid,rhiccaDatWide$pid)],
    lims.Glucose_enrolment=rhiccaDatWide$lims.Glucose_enrolment[match(pid,rhiccaDatWide$pid)],
    lims.Cholesterol_enrolment=rhiccaDatWide$lims.Cholesterol_enrolment[match(pid,rhiccaDatWide$pid)]
  ) %>%
  filter(rowSums(is.na(.))==0)
tmpDatAllAdj<-tmpDatAllAdj[order(tmpDatAllAdj$pid),]

geeModPwv<-geeglm(pwv.pwv~physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment,data=tmpDatAllAdj,id=factor(tmpDatAllAdj$pid),corstr="exchangeable")

tmpDatAllAdj<-tmpDatAllAdj %>%
  mutate(
    pwv.geeResid=residuals(geeModPwv)
  ) %>%
  group_by(visitNum,crf.PLWH) %>%
  summarise(pwvMean=mean(pwv.pwv,na.rm=T),pwvSE=sd(pwv.pwv,na.rm=T)/sqrt(sum(!is.na(pwv.pwv))),
            pwvAdjMean=mean(pwv.geeResid,na.rm=T),pwvAdjSE=sd(pwv.geeResid,na.rm=T)/sqrt(sum(!is.na(pwv.geeResid))),
            .groups="drop") 

gPWVAdj<-tmpDatAllAdj %>%
  filter(visitNum==0 | visitNum==6 | visitNum==12 | visitNum==18 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=pwvAdjMean,ymin=pwvAdjMean-1.96*pwvAdjSE,ymax=pwvAdjMean+1.96*pwvAdjSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("Adjusted PWV mean and 95% CI over time by participant group.") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("Residual PWV (m/s)") +
  labs(caption="Longitudinal PWV has been adjusted for baseline CVD risk factors\n(waist-hip ratio, systolic and diastolic blood pressure, glucose, cholesterol)\nusing a GEE model with exchangeable correlation structure.") +
  xlim(c(0,24))

gPWVAdj.notitle<-tmpDatAllAdj %>%
  filter(visitNum==0 | visitNum==6 | visitNum==12 | visitNum==18 | visitNum==24) %>%
  ggplot(mapping=aes(x=visitNum,y=pwvAdjMean,ymin=pwvAdjMean-1.96*pwvAdjSE,ymax=pwvAdjMean+1.96*pwvAdjSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none",col="none") +
  theme(text=element_text(size=12),legend.position="left") +
  xlab("Study visit (months since enrolment)") +
  ylab("Residual PWV (m/s)") +
  #labs(caption="Longitudinal PWV has been adjusted for baseline CVD risk factors\n(waist-hip ratio, systolic and diastolic blood pressure, glucose, cholesterol)\nusing a GEE model with exchangeable correlation structure.") +
  xlim(c(0,24))

#print(gPWV)
grid.arrange(gPWV,gPWVAdj,nrow=1)
PWV sample mean and 95% CI over time by participant type.

Figure 8.8: PWV sample mean and 95% CI over time by participant type.

gPWVbmi<-tmpDatBmi %>%
  ggplot(mapping=aes(x=visitNum,y=pwvMean,ymin=pwvMean-1.96*pwvSE,ymax=pwvMean+1.96*pwvSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("PWV mean and 95% CI over time by participant group.\n(Stratified by BMI.)") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("PWV (m/s)") +
  xlim(c(0,24)) +
  facet_wrap(~factor(physio.bmi_cat_enrolment,levels=c("underweight","normal","overweight","obese")),nrow=2)

print(gPWVbmi)
PWV sample mean and 95% CI over time by participant type and BMI group.

Figure 8.9: PWV sample mean and 95% CI over time by participant type and BMI group.

gPWVhyper<-tmpDatHyper %>%
  ggplot(mapping=aes(x=visitNum,y=pwvMean,ymin=pwvMean-1.96*pwvSE,ymax=pwvMean+1.96*pwvSE,col=crf.PLWH,pch=crf.PLWH,lty=crf.PLWH,fill=crf.PLWH)) +
  geom_point(size=3) +
  geom_line(lwd=1) +
  geom_ribbon(alpha=0.25,linetype=0) +
  scale_color_manual(values=c("steelblue","orange"),name="HIV status") +
  scale_fill_manual(values=c("steelblue","orange"),name="HIV status") +
  guides(fill="none",lty="none",pch="none") +
  ggtitle("PWV mean and 95% CI over time by participant group.\n(Stratified by baseline hypertension group.)") + 
  theme(text=element_text(size=16)) +
  xlab("Study visit (months since enrolment)") +
  ylab("PWV (m/s)") +
  xlim(c(0,24)) +
  facet_wrap(~physio.hypertension_cat_enrolment,nrow=1)

print(gPWVhyper)
PWV sample mean and 95% CI over time by participant type and hypertension group.

Figure 8.10: PWV sample mean and 95% CI over time by participant type and hypertension group.

8.2.2 Regression models

There are 3 models below and all are longitudinal, linear mixed models. The input data is multiply imputed data using data from the enrolments visit and visits at 6, 12, 18 and 24 months. Variables that are not immutable participant characteristics but for which only the baseline measurement has been used are indicated as such.

The first model is an an unadjusted model with only time (since baseline visits, in months) and participant type as predictors. This aims to summarise the data, but can be confounded by modifiable risk factors that affect both PWV and that are differently distributed among participant types. In this model both time and participant type are statistically significant, meaning there is evidence to suggest that PWV increased with time and is, on average, lower in PLWH compared to controls.

tmpDatWide<-rhiccaDatWide %>%
  mutate(
    pwvChange=pwv.pwv_24months-pwv.pwv_enrolment,
    cimtChange=cimt.cimt_24months-cimt.cimt_enrolment,
    abpiChange=abpi.abpi_24months-abpi.abpi_enrolment,
    egfrChange=eGFR_24months-eGFR_enrolment
  )

# LMMs - adjusted and unadjusted
obj1LmmPwv<-lmer(pwv.pwv~visitNumExactPwv+crf.ptype+(1|pid),data=rhiccaDatLong)

# obj1LmmPwv.timeonly.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+(1|pid)))
# obj1LmmPwv.ptype.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+crf.ptype+(1|pid)))
# obj1LmmPwv.sex.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+crf.gender+(1|pid)))
# obj1LmmPwv.age.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+crf.age+(1|pid)))
# obj1LmmPwv.waisthip.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+physio.waisthip_enrolment+(1|pid)))
# obj1LmmPwv.diabp.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+physio.bp_dia+(1|pid)))
# obj1LmmPwv.sysbp.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+physio.bp_sys+(1|pid)))
# obj1LmmPwv.glucose.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+lims.Glucose_enrolment+(1|pid)))
# obj1LmmPwv.cholesterol.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+lims.Cholesterol_enrolment+(1|pid)))
# obj1LmmPwv.cmv.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+cmvStatus+(1|pid)))
# obj1LmmPwv.vzv.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum+vzvStatus+(1|pid)))

rhiccaDatLong$physio.bmi_enrolment<-rhiccaDatWide$physio.bmi_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$physio.waisthip_enrolment<-rhiccaDatWide$physio.waisthip_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lims.Glucose_enrolment<-rhiccaDatWide$lims.Glucose_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lims.Cholesterol_enrolment<-rhiccaDatWide$lims.Cholesterol_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.CD163_enrolment<-rhiccaDatWide$lum.CD163_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.CD163_6months<-rhiccaDatWide$lum.CD163_6months[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.CD163_change<-(rhiccaDatWide$lum.CD163_6months-rhiccaDatWide$lum.CD163_enrolment)[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.IL6_enrolment<-rhiccaDatWide$lum.IL6_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.IL6_6months<-rhiccaDatWide$lum.IL6_6months[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.IL6_change<-(rhiccaDatWide$lum.IL6_6months-rhiccaDatWide$lum.IL6_enrolment)[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.ICAM1_enrolment<-rhiccaDatWide$lum.ICAM1_enrolment[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.ICAM1_6months<-rhiccaDatWide$lum.ICAM1_6months[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$lum.ICAM1_change<-(rhiccaDatWide$lum.ICAM1_6months-rhiccaDatWide$lum.ICAM1_enrolment)[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]
rhiccaDatLong$crf.artRegimen.2levels<-rhiccaDatWide$crf.artRegimen.2levels[match(rhiccaDatLong$pid,rhiccaDatWide$pid)]

obj1LmmPwvAdjGlucChol<-lmerTest::lmer(pwv.pwv~visitNum*crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+(1|pid),data=rhiccaDatLong)
obj1LmmPwvAdjGlucChol.mid<-with(rhiccaDatLong_impMice,lme4::lmer(pwv.pwv~visitNum*crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus+(1|pid)))

tmp<-mice::complete(rhiccaDatLong_impMice,1)
subsetHIV<-(tmp$crf.ptype=="Patient")
rhiccaDatLong_impMice.hiv<-miceadds::subset_datlist(rhiccaDatLong_impMice,subset=subsetHIV,select=NULL,expr_subset=NULL,index=NULL)
rhiccaDatLong_impMice.hiv<-miceadds::datlist2mids(rhiccaDatLong_impMice.hiv)
obj1LmmPwvAdjGlucChol.hiv.mid<-with(rhiccaDatLong_impMice.hiv,lme4::lmer(pwv.pwv~visitNum+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)+(1|pid)))
summary(pool(obj1LmmPwv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1LmmPwv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model PWV-1: Results for the linear mixed model for PWV with time and participant type as fixed factors, subject ID as random factor (random intercept only). Model fitted to multiply imputed data. Except for immutable participant characteristics, each variable is input longitudinally into the model with data from visits at enrolment, 6, 12, 18 and 24 month unless otherwise indicated.",digits=4,row_names=c("Intercept","Time since baseline visit (in months)","Participant type: PLWH"),escape=F) %>%
  kable_styling(full_width=F)

The second model is adjusted for participant characteristics and modifiable risk factors (sex, age, baseline waist-hip ratio, diastolic and systolic blood pressure, baseline glucose and baseline cholesterol). Further this model allows for a different trend over time between PLWH and controls. We note that while the overall trend over time is now weakened, it is still statistically significant and there is no evidence for a different trend over time between PLWH and control. The overall difference in PWV observed between PLWH and controls is no longer statistically significant and appears to be explained by age, diastolic and systolic blood pressure and baseline glucose values.

summary(pool(obj1LmmPwvAdjGlucChol.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1LmmPwvAdjGlucChol.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model PWV-2: Results for the linear mixed model for PWV with time, participant type and individual-level covariates as fixed factors (including glucose and cholesterol), subject ID as random factor (random intercept only). Model fitted to multiply imputed data. Except for immutable participant characteristics, each variable is input longitudinally into the model with data from visits at enrolment, 6, 12, 18 and 24 month unless otherwise indicated.",digits=4,row_names=c("Intercept","Time since baseline visit (in months)","Participant type: PLWH","Sex male","Age (in years)","BMI (baseline)","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","Change in time since baseline coefficient in PLWH"),escape=F) %>%
  kable_styling(full_width=F)

The third model is fit to data from PLWH only. It is the same model as model 2 except that additionally CD4 count and log viral load are included as predictors. As viral load is near completely suppressed by 6 months, we only use baseline viral loads. CD4 counts are measured at baseline, 6, 12 and 24 months (note that this model therefore does not use data from the 18 month visit). We include both the baseline measurement and the change from baseline in the model.

There is again a significant decrease in PWV over time and age, diastolic and systolic blood pressure and glucose have an impact on PWV as in the previous model. However there is also a strongly statistically significant decrease in PWV associatied with increasing CD4 count.

summary(pool(obj1LmmPwvAdjGlucChol.hiv.mid)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(obj1LmmPwvAdjGlucChol.hiv.mid)))) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum,term)) %>%
  kableRn(caption="Model PWV-3: Results for the linear mixed model for PWV in PLWH only with subject ID as random factor (random intercept only). Model fitted to multiply imputed data. Except for immutable participant characteristics, each variable is input longitudinally into the model with data from visits at enrolment, 6, 12 and 24 month unless otherwise indicated.",digits=4,row_names=c("Intercept","Time since baseline visit (in months)","Sex male","Age (in years)","BMI (baseline)","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CD4 absolute (baseline)","CD4 absolute (change from baseline)","log10(viral load) at baseline"),escape=F) %>%
  kable_styling(full_width=F)

Table 8.9 shows a combined summary for the 3 PWV models

#helper functions
sumFitandSum_pwv<-function(varString){
  mod<-with(rhiccaDatLong_impMice,lme4::lmer(as.formula(paste(sep="+","pwv.pwv~(1|pid)",varString))))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F)))
  
  return(sumObj)
}

sumFitandSum_pwv.hiv<-function(varString){
  mod<-with(rhiccaDatLong_impMice.hiv,lme4::lmer(as.formula(paste(sep="+","pwv.pwv~(1|pid)",varString))))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F)))
  
  return(sumObj)
}

# tab1<-summary(pool(obj1LmmPwv.mid)) %>%
#   as.data.frame() %>%
#   mutate(rownum=1:nrow(summary(pool(obj1LmmPwv.mid)))) %>%
#   mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
#   dplyr::select(!c(rownum,term))
tab1.timeonly<-sumFitandSum_pwv("visitNum")
tab1.ptype<-sumFitandSum_pwv("visitNum+crf.ptype")
tab1.sex<-sumFitandSum_pwv("visitNum+crf.gender")
tab1.age<-sumFitandSum_pwv("visitNum+crf.age")
tab1.smoke<-sumFitandSum_pwv("visitNum+crf.smoke")
tab1.alcohol<-sumFitandSum_pwv("visitNum+crf.alcohol")
tab1.waisthip<-sumFitandSum_pwv("visitNum+physio.waisthip_enrolment")
tab1.bmi<-sumFitandSum_pwv("visitNum+physio.bmi_enrolment")
tab1.diabp<-sumFitandSum_pwv("visitNum+physio.bp_dia")
tab1.sysbp<-sumFitandSum_pwv("visitNum+physio.bp_sys")
tab1.glucose<-sumFitandSum_pwv("visitNum+lims.Glucose_enrolment")
tab1.cholesterol<-sumFitandSum_pwv("visitNum+lims.Cholesterol_enrolment")
tab1.ckd<-sumFitandSum_pwv("visitNum+eGFR_existingCKD")
tab1.cmv<-sumFitandSum_pwv("visitNum+cmvStatus")
tab1.vzv<-sumFitandSum_pwv("visitNum+vzvStatus")
tab1<-rbind(tab1.timeonly,
            tab1.ptype,
            tab1.sex,
            tab1.age,
            tab1.smoke,
            tab1.alcohol,
            tab1.waisthip,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            tab1.ckd,
            tab1.cmv,
            tab1.vzv)

tab2<-sumFitandSum_pwv("visitNum*crf.ptype+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus")

tab3<-sumFitandSum_pwv.hiv("visitNum+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab4.timeonly<-sumFitandSum_pwv.hiv("visitNum")
tab4.sex<-sumFitandSum_pwv.hiv("visitNum+crf.gender")
tab4.age<-sumFitandSum_pwv.hiv("visitNum+crf.age")
tab4.smoke<-sumFitandSum_pwv.hiv("visitNum+crf.smoke")
tab4.alcohol<-sumFitandSum_pwv.hiv("visitNum+crf.alcohol")
tab4.waisthip<-sumFitandSum_pwv.hiv("visitNum+physio.waisthip_enrolment")
tab4.bmi<-sumFitandSum_pwv.hiv("visitNum+physio.bmi_enrolment")
tab4.diabp<-sumFitandSum_pwv.hiv("visitNum+physio.bp_dia")
tab4.sysbp<-sumFitandSum_pwv.hiv("visitNum+physio.bp_sys")
tab4.glucose<-sumFitandSum_pwv.hiv("visitNum+lims.Glucose_enrolment")
tab4.cholesterol<-sumFitandSum_pwv.hiv("visitNum+lims.Cholesterol_enrolment")
tab4.ckd<-sumFitandSum_pwv.hiv("visitNum+eGFR_existingCKD")
tab4.cmv<-sumFitandSum_pwv.hiv("visitNum+cmvStatus")
tab4.vzv<-sumFitandSum_pwv.hiv("visitNum+vzvStatus")
tab4.cd4base<-sumFitandSum_pwv.hiv("visitNum+lims.CD4_Absolute_enrolment")
tab4.cd4change<-sumFitandSum_pwv.hiv("visitNum+lims.CD4_Absolute")
tab4.vl<-sumFitandSum_pwv.hiv("visitNum+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab4<-rbind(tab4.timeonly,
            tab4.sex,
            tab4.age,
            tab4.smoke,
            tab4.alcohol,
            tab4.waisthip,
            tab4.bmi,
            tab4.diabp,
            tab4.sysbp,
            tab4.glucose,
            tab4.cholesterol,
            tab4.ckd,
            tab4.cmv,
            tab4.vzv,
            tab4.cd4base,
            tab4.cd4change,
            tab4.vl
)

allRows<-setdiff(unique(c(tab1$term,tab2$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA,coefficient.hivadj=NA,SE.hivadj=NA,pvalue.hivadj=NA)

tabAll$coefficient.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$SE.unadj<-tab1$std.error[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$coefficient.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$SE.adj<-tab2$std.error[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tabAll$coefficient.hivadj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.hivadj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.hivadj<-tab3$p.value[match(tabAll$term,tab3$term)]

tabAll<-tabAll

# rn<-c(
#     c("Intercept","Time since baseline visit (in months)","Participant type: PLWH"),
#     c("Intercept ","Time since baseline visit (in months) ","Participant type: PLWH ","Sex male","Age (in years)","Waist-hip ratio (baseline)","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: progression to latency","CMV: reactivation","CMV: persistently high titres","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","Change in time since baseline coefficient in PLWH"),
#     c("Intercept  ","Time since baseline visit (in months)  ","Sex male ","Age (in years) ","Waist-hip ratio (baseline) ","Diastolic blood pressure ","Systolic blood pressure ","Glucose (baseline) ","Cholesterol (baseline) ","CMV: progression to latency ","CMV: reactivation ","CMV: persistently high titres ","VZV: progression to latency ","VZV: reactivation ","VZV: persistently high titres ","CD4 absolute (baseline)","CD4 absolute (change from baseline)","log10(viral load) (baseline)")
#   )
# 
# tab %>%
#   kableRn(digits=4,escape=F,row_names=rn,caption="Model summaries for all 3 models fitted to PWV as outcome (unadjusted model, adjusted model and adjusted model for PLWH only.)") %>%
#   pack_rows(index = c("Unadjusted model, all data" = 3, "Adjusted model, all data" = 17, "Adjusted model, PLWH only" = 18)) %>%
#   kable_styling(full_width=F)

rn<-c("Time since baseline visit (in months)","Participant type: PLWH","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","Change in time since baseline coefficient in PLWH","CD4 (baseline)","CD4 (longitudinal)","log10 viral load (baseline)")

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),3),caption="Model summaries for all mixed effects models fitted to PWV as outcome (unadjusted, single variable models for all participants, multiple regression model for all participants and multiple regression model for PLWH only.)") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models, all data" = 3, "Multiple regression model, all data" = 3, "Multiple regression model, PLWH" = 3)) %>%
  kable_styling(full_width=F)
Table 8.9: Model summaries for all mixed effects models fitted to PWV as outcome (unadjusted, single variable models for all participants, multiple regression model for all participants and multiple regression model for PLWH only.)
Unadjusted models, all data
Multiple regression model, all data
Multiple regression model, PLWH
Coefficient SE p Coefficient SE p Coefficient SE p
Time since baseline visit (in months) -0.0251 0.0027 0.0000 -0.0168 0.0059 0.0043 -0.0139 0.0040 0.0007
Participant type: PLWH -0.2428 0.1212 0.0454 0.1003 0.1351 0.4578
Sex: male 0.1025 0.1015 0.3130 -0.0523 0.1052 0.6198 -0.0908 0.1192 0.4473
Age (in years) 0.0778 0.0061 0.0000 0.0630 0.0058 0.0000 0.0603 0.0071 0.0000
Current smoker 0.0728 0.1639 0.6573 0.0371 0.1561 0.8122 0.0418 0.1662 0.8015
Alcohol drinker 0.0478 0.1225 0.6967 0.1466 0.1241 0.2383 0.1280 0.1313 0.3300
Waist-hip ratio 2.0841 0.7452 0.0052 -0.7283 0.6481 0.2614 -0.7116 0.7293 0.3296
BMI 0.0101 0.0101 0.3180 -0.0100 0.0101 0.3211 -0.0096 0.0120 0.4233
Diastolic blood pressure 0.0472 0.0029 0.0000 0.0280 0.0050 0.0000 0.0324 0.0063 0.0000
Systolic blood pressure 0.0317 0.0019 0.0000 0.0136 0.0034 0.0001 0.0106 0.0041 0.0110
Glucose 0.0716 0.0257 0.0054 0.0493 0.0212 0.0199 0.0551 0.0232 0.0174
Cholesterol 0.1132 0.0446 0.0115 0.0094 0.0428 0.8259 -0.0011 0.0484 0.9813
Existing CKD 0.3579 0.2586 0.1677 0.0255 0.2131 0.9047 0.0254 0.2329 0.9132
CMV: progression to low titres -0.2632 0.3680 0.4748 -0.0776 0.3017 0.7971 -0.2147 0.3105 0.4894
CMV: progression to high titres 0.0982 0.1594 0.5384 0.1211 0.1398 0.3883 0.0841 0.1431 0.5572
CMV: persistently high titres 0.0093 0.1325 0.9439 0.0776 0.1150 0.5004 0.0306 0.1276 0.8106
VZV: progression to low titres 0.0925 0.1802 0.6088 0.0839 0.1428 0.5577 0.1255 0.1578 0.4281
VZV: progression to high titres -0.2867 0.2766 0.3022 -0.0342 0.2151 0.8738 0.0154 0.2176 0.9435
VZV: persistently high titres 0.2059 0.1484 0.1669 0.0516 0.1182 0.6629 0.0230 0.1268 0.8562
Change in time since baseline coefficient in PLWH -0.0040 0.0068 0.5567
CD4 (baseline) -0.0002 0.0003 0.4480
CD4 (longitudinal) -0.0009 0.0003 0.0015
log10 viral load (baseline) 0.0158 0.0388 0.6839
write.csv(tabAll,row.names=F,file=paste(sep="_",outPrefix,"PWV_regressionModels.csv"))

tabAll.pwv<-tabAll
tab4$term<-as.character(tab4$term)
tab3$term<-as.character(tab3$term)
allRows<-setdiff(unique(c(tab4$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA)

tabAll$coefficient.unadj<-tab4$estimate[match(tabAll$term,tab4$term)]
tabAll$SE.unadj<-tab4$std.error[match(tabAll$term,tab4$term)]
tabAll$pvalue.unadj<-tab4$p.value[match(tabAll$term,tab4$term)]

tabAll$coefficient.adj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.adj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.adj<-tab3$p.value[match(tabAll$term,tab3$term)]

rn<-c("Time since baseline visit (in months)","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (longitudinal)","log10 viral load (baseline)")

options(knitr.kable.NA = '')

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),2),caption="Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.") %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  kable_styling(full_width=F)
Table 8.10: Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p
Time since baseline visit (in months) -0.0258 0.0032 0.0000 -0.0139 0.0040 0.0007
Sex: male 0.1238 0.1127 0.2723 -0.0908 0.1192 0.4473
Age (in years) 0.0714 0.0075 0.0000 0.0603 0.0071 0.0000
Current smoker -0.0461 0.1710 0.7874 0.0418 0.1662 0.8015
Alcohol drinker 0.0795 0.1254 0.5261 0.1280 0.1313 0.3300
Waist-hip ratio 1.4778 0.8260 0.0741 -0.7116 0.7293 0.3296
BMI 0.0044 0.0125 0.7215 -0.0096 0.0120 0.4233
Diastolic blood pressure 0.0472 0.0032 0.0000 0.0324 0.0063 0.0000
Systolic blood pressure 0.0307 0.0022 0.0000 0.0106 0.0041 0.0110
Glucose (baseline) 0.0727 0.0272 0.0077 0.0551 0.0232 0.0174
Cholesterol (baseline) 0.0716 0.0524 0.1724 -0.0011 0.0484 0.9813
Existing CKD 0.2933 0.2835 0.3025 0.0254 0.2329 0.9132
CMV: progression to low titres -0.2952 0.3753 0.4319 -0.2147 0.3105 0.4894
CMV: progression to high titres 0.1934 0.1545 0.2111 0.0841 0.1431 0.5572
CMV: persistently high titres 0.1039 0.1370 0.4484 0.0306 0.1276 0.8106
VZV: progression to low titres 0.1312 0.1957 0.5046 0.1255 0.1578 0.4281
VZV: progression to high titres -0.2537 0.2653 0.3402 0.0154 0.2176 0.9435
VZV: persistently high titres 0.1520 0.1568 0.3341 0.0230 0.1268 0.8562
CD4 (baseline) -0.0002 0.0003 0.4890 -0.0002 0.0003 0.4480
CD4 (longitudinal) -0.0011 0.0003 2e-04 -0.0009 0.0003 0.0015
log10 viral load (baseline) 0.0094 0.0386 0.8071 0.0158 0.0388 0.6839
tabAll.pwv.hiv<-tabAll

8.3 Combining CIMT and PWV on a single table

tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="physio.bp_dia_enrolment"]<-"physio.bp_dia"
tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="physio.bp_sys_enrolment"]<-"physio.bp_sys"
tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="lims.CD4_Absolute_changeFromBaselineAt24Months"]<-"lims.CD4_Absolute"

allRows<-unique(c("cimt.cimt_enrolment","visitNum",tabAll.cimt.hiv$term,tabAll.pwv.hiv$term))

tabAll<-data.frame(term=allRows,
                   cimt.coefficient.unadj=NA,cimt.SE.unadj=NA,cimt.pvalue.unadj=NA,cimt.coefficient.adj=NA,cimt.SE.adj=NA,cimt.pvalue.adj=NA,
                   pwv.coefficient.unadj=NA,pwv.SE.unadj=NA,pwv.pvalue.unadj=NA,pwv.coefficient.adj=NA,pwv.SE.adj=NA,pwv.pvalue.adj=NA)

tabAll$cimt.coefficient.unadj<-tabAll.cimt.hiv$coefficient.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.SE.unadj<-tabAll.cimt.hiv$SE.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.pvalue.unadj<-tabAll.cimt.hiv$pvalue.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.coefficient.adj<-tabAll.cimt.hiv$coefficient.adj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.SE.adj<-tabAll.cimt.hiv$SE.adj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.pvalue.adj<-tabAll.cimt.hiv$pvalue.adj[match(allRows,tabAll.cimt.hiv$term)]

tabAll$pwv.coefficient.unadj<-tabAll.pwv.hiv$coefficient.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.SE.unadj<-tabAll.pwv.hiv$SE.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.pvalue.unadj<-tabAll.pwv.hiv$pvalue.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.coefficient.adj<-tabAll.pwv.hiv$coefficient.adj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.SE.adj<-tabAll.pwv.hiv$SE.adj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.pvalue.adj<-tabAll.pwv.hiv$pvalue.adj[match(allRows,tabAll.pwv.hiv$term)]

options(knitr.kable.NA = '')

rn<-c("CIMT (baseline)","Time since baseline visit (in months)","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure (baseline) *","Systolic blood pressure (baseline) *","Glucose (baseline)","Cholesterol (baseline)","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline) *","log10 viral load (baseline)")

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),4),caption="Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.") %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"CIMT"=6,"PWV"=6)) %>%
  kable_styling(full_width=F)
Table 8.11: Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.
CIMT
PWV
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p Coefficient SE p Coefficient SE p
CIMT (baseline) 0.1034 0.0538 0.058 0.0558 0.0704 0.432
Time since baseline visit (in months) -0.0258 0.0032 0.0000 -0.0139 0.0040 0.0007
Sex: male 0.0011 0.0073 0.876 -0.0044 0.0086 0.611 0.1238 0.1127 0.2723 -0.0908 0.1192 0.4473
Age (in years) 0.0011 0.0007 0.133 0.0010 0.0008 0.195 0.0714 0.0075 0.0000 0.0603 0.0071 0.0000
Current smoker -0.0034 0.0103 0.742 -0.0071 0.0122 0.559 -0.0461 0.1710 0.7874 0.0418 0.1662 0.8015
Alcohol drinker -0.0006 0.0085 0.946 0.0026 0.0099 0.795 0.0795 0.1254 0.5261 0.1280 0.1313 0.3300
Waist-hip ratio -0.0311 0.0517 0.548 -0.0416 0.0547 0.447 1.4778 0.8260 0.0741 -0.7116 0.7293 0.3296
BMI -0.0011 0.0009 0.222 -0.0006 0.0010 0.548 0.0044 0.0125 0.7215 -0.0096 0.0120 0.4233
Diastolic blood pressure (baseline) * -0.0001 0.0003 0.693 -0.0005 0.0006 0.369 0.0472 0.0032 0.0000 0.0324 0.0063 0.0000
Systolic blood pressure (baseline) * 0.0000 0.0002 0.875 0.0004 0.0004 0.290 0.0307 0.0022 0.0000 0.0106 0.0041 0.0110
Glucose (baseline) 0.0009 0.0017 0.611 0.0011 0.0018 0.546 0.0727 0.0272 0.0077 0.0551 0.0232 0.0174
Cholesterol (baseline) -0.0046 0.0036 0.205 -0.0044 0.0037 0.244 0.0716 0.0524 0.1724 -0.0011 0.0484 0.9813
Existing CKD -0.0139 0.0165 0.401 -0.0184 0.0168 0.275 0.2933 0.2835 0.3025 0.0254 0.2329 0.9132
CMV: progression to low titres -0.0082 0.0226 0.716 -0.0011 0.0234 0.961 -0.2952 0.3753 0.4319 -0.2147 0.3105 0.4894
CMV: progression to high titres 0.0174 0.0093 0.062 0.0144 0.0098 0.142 0.1934 0.1545 0.2111 0.0841 0.1431 0.5572
CMV: persistently high titres 0.0081 0.0097 0.403 0.0074 0.0101 0.461 0.1039 0.1370 0.4484 0.0306 0.1276 0.8106
VZV: progression to low titres 0.0222 0.0117 0.061 0.0219 0.0120 0.071 0.1312 0.1957 0.5046 0.1255 0.1578 0.4281
VZV: progression to high titres 0.0039 0.0156 0.801 0.0064 0.0158 0.684 -0.2537 0.2653 0.3402 0.0154 0.2176 0.9435
VZV: persistently high titres 0.0198 0.0092 0.032 0.0187 0.0093 0.046 0.1520 0.1568 0.3341 0.0230 0.1268 0.8562
CD4 (baseline) 0.0000 0.0000 0.668 0.0000 0.0000 0.592 -0.0002 0.0003 0.4890 -0.0002 0.0003 0.4480
CD4 (change from baseline) * 0.0000 0.0000 0.335 0.0000 0.0000 0.241 -0.0011 0.0003 2e-04 -0.0009 0.0003 0.0015
log10 viral load (baseline) 0.0011 0.0025 0.664 0.0001 0.0029 0.966 0.0094 0.0386 0.8071 0.0158 0.0388 0.6839
tabAll$pwv.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$pwv.pvalue.adj)))
tabAll$pwv.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",gsub(pattern="<span.*>2",replace="2",tabAll$pwv.pvalue.unadj))))
tabAll$cimt.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.adj)))
tabAll$cimt.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.unadj)))
write.csv(tabAll,row.names = F,file=paste(sep="_",outPrefix,"CIMT_PWV_PLWH_Table2.csv"))

8.4 Repeating this for all participants

tabAll.cimt$term[tabAll.cimt$term=="physio.bp_dia_enrolment"]<-"physio.bp_dia"
tabAll.cimt$term[tabAll.cimt$term=="physio.bp_sys_enrolment"]<-"physio.bp_sys"
tabAll.cimt$term[tabAll.cimt$term=="lims.CD4_Absolute_changeFromBaselineAt24Months"]<-"lims.CD4_Absolute"

allRows<-setdiff(unique(c("cimt.cimt_enrolment","visitNum",tabAll.cimt$term,tabAll.pwv$term)),c("lims.CD4_Absolute_enrolment","lims.CD4_Absolute","log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)"))

tabAll<-data.frame(term=allRows,
                   cimt.coefficient.unadj=NA,cimt.SE.unadj=NA,cimt.pvalue.unadj=NA,cimt.coefficient.adj=NA,cimt.SE.adj=NA,cimt.pvalue.adj=NA,
                   pwv.coefficient.unadj=NA,pwv.SE.unadj=NA,pwv.pvalue.unadj=NA,pwv.coefficient.adj=NA,pwv.SE.adj=NA,pwv.pvalue.adj=NA)

tabAll$cimt.coefficient.unadj<-tabAll.cimt$coefficient.unadj[match(allRows,tabAll.cimt$term)]
tabAll$cimt.SE.unadj<-tabAll.cimt$SE.unadj[match(allRows,tabAll.cimt$term)]
tabAll$cimt.pvalue.unadj<-tabAll.cimt$pvalue.unadj[match(allRows,tabAll.cimt$term)]
tabAll$cimt.coefficient.adj<-tabAll.cimt$coefficient.adj[match(allRows,tabAll.cimt$term)]
tabAll$cimt.SE.adj<-tabAll.cimt$SE.adj[match(allRows,tabAll.cimt$term)]
tabAll$cimt.pvalue.adj<-tabAll.cimt$pvalue.adj[match(allRows,tabAll.cimt$term)]

tabAll$pwv.coefficient.unadj<-tabAll.pwv$coefficient.unadj[match(allRows,tabAll.pwv$term)]
tabAll$pwv.SE.unadj<-tabAll.pwv$SE.unadj[match(allRows,tabAll.pwv$term)]
tabAll$pwv.pvalue.unadj<-tabAll.pwv$pvalue.unadj[match(allRows,tabAll.pwv$term)]
tabAll$pwv.coefficient.adj<-tabAll.pwv$coefficient.adj[match(allRows,tabAll.pwv$term)]
tabAll$pwv.SE.adj<-tabAll.pwv$SE.adj[match(allRows,tabAll.pwv$term)]
tabAll$pwv.pvalue.adj<-tabAll.pwv$pvalue.adj[match(allRows,tabAll.pwv$term)]

options(knitr.kable.NA = '')

rn<-c("CIMT (baseline)","Time since baseline visit (in months)","Participant type: PLWH","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure (baseline) *","Systolic blood pressure (baseline) *","Glucose (baseline)","Cholesterol (baseline)","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","Interaction term: time since baseline x participant type")

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),4),caption="Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to data from all study participants. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.") %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"CIMT"=6,"PWV"=6)) %>%
  kable_styling(full_width=F)
Table 8.12: Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to data from all study participants. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.
CIMT
PWV
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p Coefficient SE p Coefficient SE p
CIMT (baseline) 0.0427 0.0431 0.326 0.0085 0.0558 0.880
Time since baseline visit (in months) -0.0251 0.0027 0.0000 -0.0168 0.0059 0.0043
Participant type: PLWH 0.0164 0.0068 0.017 0.0098 0.0082 0.233 -0.2428 0.1212 0.0454 0.1003 0.1351 0.4578
Sex: male 0.0016 0.0059 0.790 -0.0032 0.0068 0.636 0.1025 0.1015 0.3130 -0.0523 0.1052 0.6198
Age (in years) 0.0008 0.0006 0.178 0.0008 0.0006 0.179 0.0778 0.0061 0.0000 0.0630 0.0058 0.0000
Current smoker -0.0043 0.0087 0.620 -0.0068 0.0105 0.515 0.0728 0.1639 0.6573 0.0371 0.1561 0.8122
Alcohol drinker 0.0005 0.0073 0.942 0.0025 0.0088 0.774 0.0478 0.1225 0.6967 0.1466 0.1241 0.2383
Waist-hip ratio -0.0387 0.0435 0.374 -0.0434 0.0461 0.347 2.0841 0.7452 0.0052 -0.7283 0.6481 0.2614
BMI -0.0010 0.0006 0.092 -0.0001 0.0007 0.886 0.0101 0.0101 0.3180 -0.0100 0.0101 0.3211
Diastolic blood pressure (baseline) * -0.0002 0.0002 0.355 -0.0004 0.0005 0.476 0.0472 0.0029 0.0000 0.0280 0.0050 0.0000
Systolic blood pressure (baseline) * -0.0001 0.0001 0.555 0.0002 0.0003 0.494 0.0317 0.0019 0.0000 0.0136 0.0034 0.0001
Glucose (baseline) 0.0002 0.0014 0.898 0.0005 0.0015 0.739 0.0716 0.0257 0.0054 0.0493 0.0212 0.0199
Cholesterol (baseline) -0.0046 0.0027 0.086 -0.0022 0.0030 0.467 0.1132 0.0446 0.0115 0.0094 0.0428 0.8259
Existing CKD -0.0087 0.0136 0.521 -0.0133 0.0138 0.339 0.3579 0.2586 0.1677 0.0255 0.2131 0.9047
CMV: progression to low titres -0.0081 0.0202 0.687 -0.0069 0.0205 0.736 -0.2632 0.3680 0.4748 -0.0776 0.3017 0.7971
CMV: progression to high titres 0.0179 0.0082 0.030 0.0123 0.0084 0.143 0.0982 0.1594 0.5384 0.1211 0.1398 0.3883
CMV: persistently high titres 0.0114 0.0087 0.193 0.0071 0.0088 0.423 0.0093 0.1325 0.9439 0.0776 0.1150 0.5004
VZV: progression to low titres 0.0201 0.0097 0.041 0.0182 0.0097 0.062 0.0925 0.1802 0.6088 0.0839 0.1428 0.5577
VZV: progression to high titres 0.0049 0.0139 0.725 0.0052 0.0142 0.714 -0.2867 0.2766 0.3022 -0.0342 0.2151 0.8738
VZV: persistently high titres 0.0163 0.0078 0.037 0.0137 0.0079 0.083 0.2059 0.1484 0.1669 0.0516 0.1182 0.6629
Interaction term: time since baseline x participant type -0.0040 0.0068 0.5567
tabAll$pwv.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$pwv.pvalue.adj)))
tabAll$pwv.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",gsub(pattern="<span.*>2",replace="2",tabAll$pwv.pvalue.unadj))))
tabAll$cimt.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.adj)))
tabAll$cimt.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.unadj)))
write.csv(tabAll,row.names = F,file=paste(sep="_",outPrefix,"CIMT_PWV_AllParticipants_TableS4.csv"))

8.5 Repeating this while including ART treatment

# CIMT
tab3<-sumFitandSum_cimt.hiv("+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)+crf.artRegimen.2levels")

tab4.baseline<-sumFitandSum_cimt.hiv("")
tab4.sex<-sumFitandSum_cimt.hiv("+crf.gender")
tab4.age<-sumFitandSum_cimt.hiv("+crf.age")
tab4.smoke<-sumFitandSum_cimt.hiv("+crf.smoke")
tab4.alcohol<-sumFitandSum_cimt.hiv("+crf.alcohol")
tab4.waisthip<-sumFitandSum_cimt.hiv("+physio.waisthip_enrolment")
tab4.bmi<-sumFitandSum_cimt.hiv("+physio.bmi_enrolment")
tab4.diabp<-sumFitandSum_cimt.hiv("+physio.bp_dia_enrolment")
tab4.sysbp<-sumFitandSum_cimt.hiv("+physio.bp_sys_enrolment")
tab4.glucose<-sumFitandSum_cimt.hiv("+lims.Glucose_enrolment")
tab4.cholesterol<-sumFitandSum_cimt.hiv("+lims.Cholesterol_enrolment")
tab4.ckd<-sumFitandSum_cimt.hiv("+eGFR_existingCKD")
tab4.cmv<-sumFitandSum_cimt.hiv("+cmvStatus")
tab4.vzv<-sumFitandSum_cimt.hiv("+vzvStatus")
tab4.cd4base<-sumFitandSum_cimt.hiv("+lims.CD4_Absolute_enrolment")
tab4.cd4change<-sumFitandSum_cimt.hiv("+lims.CD4_Absolute_changeFromBaselineAt24Months")
tab4.vl<-sumFitandSum_cimt.hiv("+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab4.art<-sumFitandSum_cimt.hiv("+crf.artRegimen.2levels")

tab4<-rbind(tab4.baseline,
            tab4.sex,
            tab4.age,
            tab4.smoke,
            tab4.alcohol,
            tab4.waisthip,
            tab4.bmi,
            tab4.diabp,
            tab4.sysbp,
            tab4.glucose,
            tab4.cholesterol,
            tab4.ckd,
            tab4.cmv,
            tab4.vzv,
            tab4.cd4base,
            tab4.cd4change,
            tab4.vl,
            tab4.art
)


tab4$term<-as.character(tab4$term)
tab3$term<-as.character(tab3$term)
allRows<-setdiff(unique(c(tab4$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA)

tabAll$coefficient.unadj<-tab4$estimate[match(tabAll$term,tab4$term)]
tabAll$SE.unadj<-tab4$std.error[match(tabAll$term,tab4$term)]
tabAll$pvalue.unadj<-tab4$p.value[match(tabAll$term,tab4$term)]

tabAll$coefficient.adj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.adj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.adj<-tab3$p.value[match(tabAll$term,tab3$term)]

rn<-c("Baseline CIMT","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from Baseline at 24 months)","log10 viral load (baseline)","ART: no change to dolutegravir")

options(knitr.kable.NA = '')

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),2),caption="Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  kable_styling(full_width=F)
Table 8.13: Model summaries for all models fitted to CIMT as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p
Baseline CIMT 0.103 0.054 0.058 0.054 0.070 0.451
Sex: male 0.001 0.007 0.876 -0.005 0.009 0.544
Age (in years) 0.001 0.001 0.133 0.001 0.001 0.187
Current smoker -0.003 0.010 0.742 -0.007 0.012 0.586
Alcohol drinker -0.001 0.009 0.946 0.002 0.010 0.833
Waist-hip ratio -0.031 0.052 0.548 -0.042 0.055 0.448
BMI -0.001 0.001 0.222 -0.001 0.001 0.550
Diastolic blood pressure 0.000 0.000 0.693 -0.001 0.001 0.377
Systolic blood pressure 0.000 0.000 0.875 0.000 0.000 0.294
Glucose 0.001 0.002 0.611 0.001 0.002 0.557
Cholesterol -0.005 0.004 0.205 -0.004 0.004 0.244
Existing CKD -0.014 0.017 0.401 -0.018 0.017 0.289
CMV: progression to low titres -0.008 0.023 0.716 -0.002 0.023 0.927
CMV: progression to high titres 0.017 0.009 0.062 0.015 0.010 0.135
CMV: persistently high titres 0.008 0.010 0.403 0.008 0.010 0.425
VZV: progression to low titres 0.022 0.012 0.061 0.021 0.012 0.076
VZV: progression to high titres 0.004 0.016 0.801 0.006 0.016 0.715
VZV: persistently high titres 0.020 0.009 0.032 0.019 0.009 0.047
CD4 (baseline) 0.000 0.000 0.668 0.000 0.000 0.588
CD4 (change from Baseline at 24 months) 0.000 0.000 0.335 0.000 0.000 0.253
log10 viral load (baseline) 0.001 0.003 0.664 0.000 0.003 0.988
ART: no change to dolutegravir -0.005 0.007 0.444 -0.005 0.007 0.442
tabAll.cimt.hiv<-tabAll

Note that the intercept in the unadjusted model gives the average change in CIMT over 24 months:

sumFitandSum_cimt.hiv("-cimt.cimt_enrolment") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.14: Model summary for the basic unadjusted model fitted to CIMT as outcome. Model fitted to PLWH only.
Coefficient SE p
(Intercept) 0.033 0.003 <0.001

We can also pull this out for the adjusted model:

tab3 %>%
  dplyr::filter(term=="(Intercept)") %>%
  dplyr::select(!c(term,rownum,statistic,df)) %>%
  kableRn(digits=3,escape=F,row_names=c("(Intercept)"),col.names=c("Coefficient","SE","p"),caption="Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to PLWH only but including ART treatment.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  kable_styling(full_width=F)
Table 8.15: Model summary (showing intercept only!) for the fully adjusted model fitted to CIMT as outcome. Model fitted to PLWH only but including ART treatment.
Coefficient SE p
(Intercept) 0.002 0.057 0.972
# PWV
tab3<-sumFitandSum_pwv.hiv("visitNum+crf.gender+crf.age+crf.smoke+crf.alcohol+physio.waisthip_enrolment+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+eGFR_existingCKD+cmvStatus+vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)+crf.artRegimen.2levels")

tab4.timeonly<-sumFitandSum_pwv.hiv("visitNum")
tab4.sex<-sumFitandSum_pwv.hiv("visitNum+crf.gender")
tab4.age<-sumFitandSum_pwv.hiv("visitNum+crf.age")
tab4.smoke<-sumFitandSum_pwv.hiv("visitNum+crf.smoke")
tab4.alcohol<-sumFitandSum_pwv.hiv("visitNum+crf.alcohol")
tab4.waisthip<-sumFitandSum_pwv.hiv("visitNum+physio.waisthip_enrolment")
tab4.bmi<-sumFitandSum_pwv.hiv("visitNum+physio.bmi_enrolment")
tab4.diabp<-sumFitandSum_pwv.hiv("visitNum+physio.bp_dia")
tab4.sysbp<-sumFitandSum_pwv.hiv("visitNum+physio.bp_sys")
tab4.glucose<-sumFitandSum_pwv.hiv("visitNum+lims.Glucose_enrolment")
tab4.cholesterol<-sumFitandSum_pwv.hiv("visitNum+lims.Cholesterol_enrolment")
tab4.ckd<-sumFitandSum_pwv.hiv("visitNum+eGFR_existingCKD")
tab4.cmv<-sumFitandSum_pwv.hiv("visitNum+cmvStatus")
tab4.vzv<-sumFitandSum_pwv.hiv("visitNum+vzvStatus")
tab4.cd4base<-sumFitandSum_pwv.hiv("visitNum+lims.CD4_Absolute_enrolment")
tab4.cd4change<-sumFitandSum_pwv.hiv("visitNum+lims.CD4_Absolute")
tab4.vl<-sumFitandSum_pwv.hiv("visitNum+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab4.art<-sumFitandSum_pwv.hiv("crf.artRegimen.2levels")

tab4<-rbind(tab4.timeonly,
            tab4.sex,
            tab4.age,
            tab4.smoke,
            tab4.alcohol,
            tab4.waisthip,
            tab4.bmi,
            tab4.diabp,
            tab4.sysbp,
            tab4.glucose,
            tab4.cholesterol,
            tab4.ckd,
            tab4.cmv,
            tab4.vzv,
            tab4.cd4base,
            tab4.cd4change,
            tab4.vl,
            tab4.art
)

tab4$term<-as.character(tab4$term)
tab3$term<-as.character(tab3$term)
allRows<-setdiff(unique(c(tab4$term,tab3$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coefficient.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coefficient.adj=NA,SE.adj=NA,pvalue.adj=NA)

tabAll$coefficient.unadj<-tab4$estimate[match(tabAll$term,tab4$term)]
tabAll$SE.unadj<-tab4$std.error[match(tabAll$term,tab4$term)]
tabAll$pvalue.unadj<-tab4$p.value[match(tabAll$term,tab4$term)]

tabAll$coefficient.adj<-tab3$estimate[match(tabAll$term,tab3$term)]
tabAll$SE.adj<-tab3$std.error[match(tabAll$term,tab3$term)]
tabAll$pvalue.adj<-tab3$p.value[match(tabAll$term,tab3$term)]

rn<-c("Time since baseline visit (in months)","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (longitudinal)","log10 viral load (baseline)","ART: no change to dolutegravir")

options(knitr.kable.NA = '')

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),2),caption="Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.") %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  kable_styling(full_width=F)
Table 8.16: Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only.
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p
Time since baseline visit (in months) -0.0258 0.0032 0.0000 -0.0139 0.0040 0.0007
Sex: male 0.1238 0.1127 0.2723 -0.0983 0.1201 0.4143
Age (in years) 0.0714 0.0075 0.0000 0.0603 0.0071 0.0000
Current smoker -0.0461 0.1710 0.7874 0.0460 0.1661 0.7821
Alcohol drinker 0.0795 0.1254 0.5261 0.1234 0.1312 0.3473
Waist-hip ratio 1.4778 0.8260 0.0741 -0.7116 0.7297 0.3298
BMI 0.0044 0.0125 0.7215 -0.0097 0.0120 0.4205
Diastolic blood pressure 0.0472 0.0032 0.0000 0.0325 0.0063 0.0000
Systolic blood pressure 0.0307 0.0022 0.0000 0.0104 0.0041 0.0117
Glucose (baseline) 0.0727 0.0272 0.0077 0.0548 0.0232 0.0180
Cholesterol (baseline) 0.0716 0.0524 0.1724 -0.0013 0.0485 0.9780
Existing CKD 0.2933 0.2835 0.3025 0.0302 0.2333 0.8970
CMV: progression to low titres -0.2952 0.3753 0.4319 -0.2240 0.3114 0.4721
CMV: progression to high titres 0.1934 0.1545 0.2111 0.0868 0.1433 0.5457
CMV: persistently high titres 0.1039 0.1370 0.4484 0.0369 0.1281 0.7735
VZV: progression to low titres 0.1312 0.1957 0.5046 0.1209 0.1589 0.4483
VZV: progression to high titres -0.2537 0.2653 0.3402 0.0096 0.2181 0.9648
VZV: persistently high titres 0.1520 0.1568 0.3341 0.0221 0.1267 0.8618
CD4 (baseline) -0.0002 0.0003 0.4890 -0.0002 0.0003 0.4541
CD4 (longitudinal) -0.0011 0.0003 2e-04 -0.0009 0.0003 0.0014
log10 viral load (baseline) 0.0094 0.0386 0.8071 0.0150 0.0388 0.7000
ART: no change to dolutegravir -0.0655 0.1054 0.5343 -0.0493 0.0899 0.5836
tabAll.pwv.hiv<-tabAll

# Combining CIMT and PWV
tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="physio.bp_dia_enrolment"]<-"physio.bp_dia"
tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="physio.bp_sys_enrolment"]<-"physio.bp_sys"
tabAll.cimt.hiv$term[tabAll.cimt.hiv$term=="lims.CD4_Absolute_changeFromBaselineAt24Months"]<-"lims.CD4_Absolute"

allRows<-unique(c("cimt.cimt_enrolment","visitNum",tabAll.cimt.hiv$term,tabAll.pwv.hiv$term))

tabAll<-data.frame(term=allRows,
                   cimt.coefficient.unadj=NA,cimt.SE.unadj=NA,cimt.pvalue.unadj=NA,cimt.coefficient.adj=NA,cimt.SE.adj=NA,cimt.pvalue.adj=NA,
                   pwv.coefficient.unadj=NA,pwv.SE.unadj=NA,pwv.pvalue.unadj=NA,pwv.coefficient.adj=NA,pwv.SE.adj=NA,pwv.pvalue.adj=NA)

tabAll$cimt.coefficient.unadj<-tabAll.cimt.hiv$coefficient.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.SE.unadj<-tabAll.cimt.hiv$SE.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.pvalue.unadj<-tabAll.cimt.hiv$pvalue.unadj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.coefficient.adj<-tabAll.cimt.hiv$coefficient.adj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.SE.adj<-tabAll.cimt.hiv$SE.adj[match(allRows,tabAll.cimt.hiv$term)]
tabAll$cimt.pvalue.adj<-tabAll.cimt.hiv$pvalue.adj[match(allRows,tabAll.cimt.hiv$term)]

tabAll$pwv.coefficient.unadj<-tabAll.pwv.hiv$coefficient.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.SE.unadj<-tabAll.pwv.hiv$SE.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.pvalue.unadj<-tabAll.pwv.hiv$pvalue.unadj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.coefficient.adj<-tabAll.pwv.hiv$coefficient.adj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.SE.adj<-tabAll.pwv.hiv$SE.adj[match(allRows,tabAll.pwv.hiv$term)]
tabAll$pwv.pvalue.adj<-tabAll.pwv.hiv$pvalue.adj[match(allRows,tabAll.pwv.hiv$term)]

options(knitr.kable.NA = '')

rn<-c("CIMT (baseline)","Time since baseline visit (in months)","Sex: male","Age (in years)","Current smoker","Alcohol drinker","Waist-hip ratio","BMI","Diastolic blood pressure (baseline) *","Systolic blood pressure (baseline) *","Glucose (baseline)","Cholesterol (baseline)","Existing CKD","CMV: progression to low titres","CMV: progression to high titres","CMV: persistently high titres","VZV: progression to low titres","VZV: progression to high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline) *","log10 viral load (baseline)","ART: no change from dolutegravir")

tabAll %>%
  dplyr::select(!term) %>%
  kableRn(digits=4,escape=F,row_names=rn,col.names=rep(c("Coefficient","SE","p"),4),caption="Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.") %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"CIMT"=6,"PWV"=6)) %>%
  kable_styling(full_width=F)
Table 8.16: Model summaries for all models fitted to PWV as outcome (unadjusted, single variable models and multiple regression model.). Models fitted to PLWH only. Predictors indicated with an asterisks have longitudinal values for the PWV models and values as indicated in brackets for the CIMT models.
CIMT
PWV
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Coefficient SE p Coefficient SE p Coefficient SE p Coefficient SE p
CIMT (baseline) 0.1034 0.0538 0.058 0.0535 0.0705 0.451
Time since baseline visit (in months) -0.0258 0.0032 0.0000 -0.0139 0.0040 0.0007
Sex: male 0.0011 0.0073 0.876 -0.0053 0.0087 0.544 0.1238 0.1127 0.2723 -0.0983 0.1201 0.4143
Age (in years) 0.0011 0.0007 0.133 0.0010 0.0008 0.187 0.0714 0.0075 0.0000 0.0603 0.0071 0.0000
Current smoker -0.0034 0.0103 0.742 -0.0067 0.0122 0.586 -0.0461 0.1710 0.7874 0.0460 0.1661 0.7821
Alcohol drinker -0.0006 0.0085 0.946 0.0021 0.0099 0.833 0.0795 0.1254 0.5261 0.1234 0.1312 0.3473
Waist-hip ratio -0.0311 0.0517 0.548 -0.0416 0.0547 0.448 1.4778 0.8260 0.0741 -0.7116 0.7297 0.3298
BMI -0.0011 0.0009 0.222 -0.0006 0.0010 0.550 0.0044 0.0125 0.7215 -0.0097 0.0120 0.4205
Diastolic blood pressure (baseline) * -0.0001 0.0003 0.693 -0.0005 0.0006 0.377 0.0472 0.0032 0.0000 0.0325 0.0063 0.0000
Systolic blood pressure (baseline) * 0.0000 0.0002 0.875 0.0004 0.0004 0.294 0.0307 0.0022 0.0000 0.0104 0.0041 0.0117
Glucose (baseline) 0.0009 0.0017 0.611 0.0010 0.0018 0.557 0.0727 0.0272 0.0077 0.0548 0.0232 0.0180
Cholesterol (baseline) -0.0046 0.0036 0.205 -0.0044 0.0037 0.244 0.0716 0.0524 0.1724 -0.0013 0.0485 0.9780
Existing CKD -0.0139 0.0165 0.401 -0.0178 0.0168 0.289 0.2933 0.2835 0.3025 0.0302 0.2333 0.8970
CMV: progression to low titres -0.0082 0.0226 0.716 -0.0022 0.0234 0.927 -0.2952 0.3753 0.4319 -0.2240 0.3114 0.4721
CMV: progression to high titres 0.0174 0.0093 0.062 0.0147 0.0098 0.135 0.1934 0.1545 0.2111 0.0868 0.1433 0.5457
CMV: persistently high titres 0.0081 0.0097 0.403 0.0081 0.0101 0.425 0.1039 0.1370 0.4484 0.0369 0.1281 0.7735
VZV: progression to low titres 0.0222 0.0117 0.061 0.0215 0.0120 0.076 0.1312 0.1957 0.5046 0.1209 0.1589 0.4483
VZV: progression to high titres 0.0039 0.0156 0.801 0.0058 0.0158 0.715 -0.2537 0.2653 0.3402 0.0096 0.2181 0.9648
VZV: persistently high titres 0.0198 0.0092 0.032 0.0186 0.0093 0.047 0.1520 0.1568 0.3341 0.0221 0.1267 0.8618
CD4 (baseline) 0.0000 0.0000 0.668 0.0000 0.0000 0.588 -0.0002 0.0003 0.4890 -0.0002 0.0003 0.4541
CD4 (change from baseline) * 0.0000 0.0000 0.335 0.0000 0.0000 0.253 -0.0011 0.0003 2e-04 -0.0009 0.0003 0.0014
log10 viral load (baseline) 0.0011 0.0025 0.664 0.0000 0.0029 0.988 0.0094 0.0386 0.8071 0.0150 0.0388 0.7000
ART: no change from dolutegravir -0.0054 0.0070 0.444 -0.0054 0.0070 0.442 -0.0655 0.1054 0.5343 -0.0493 0.0899 0.5836
tabAll$pwv.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$pwv.pvalue.adj)))
tabAll$pwv.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",gsub(pattern="<span.*>2",replace="2",tabAll$pwv.pvalue.unadj))))
tabAll$cimt.pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.adj)))
tabAll$cimt.pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt.pvalue.unadj)))
write.csv(tabAll,row.names = F,file=paste(sep="_",outPrefix,"CIMT_PWV_PLWH_withART_TableS3.csv"))

9 Summary of clinical and sub-clinical events

To provide a bit of context for the CVD and systemic event sections to follow, in Table 9.1 we summarise clinical and sub-clinical events, overall and for specific strata.

clinEventsTmp<-data.frame(
  pid=character(0),
  ptype=character(0),
  artnaive=integer(0),
  artRegimen=character(0),
  gender=character(0),
  age_group=character(0),
  cmvStatus=character(0),
  vzvStatus=character(0),
  cmvStatus_2levels=character(0),
  vzvStatus_2levels=character(0),
  eGFR_existingCKD=character(0),
  category=character(0)
)

pidDeath<-unique(c(ltfuDat$pid[ltfuDat$reason=="DEATH"]),clinEventsDat$PID[clinEventsDat$DIAGNOSIS=="death"])

for(j in which(!is.na(rhiccaDatWide$clinEventCategoryConfirmed) & rhiccaDatWide$clinEventCategoryConfirmed!="")){
  cats<-strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmed[j])
  clinEventsTmp<-rbind(clinEventsTmp,data.frame(pid=rhiccaDatWide$pid[j],ptype=rhiccaDatWide$crf.PLWH[j],artnaive=rhiccaDatWide$crf.artnaive[j],artRegimen=rhiccaDatWide$crf.artRegimen.2levels[j],gender=rhiccaDatWide$crf.gender[j],age_group=rhiccaDatWide$crf.age_group[j],cmvStatus=rhiccaDatWide$cmvStatus[j],vzvStatus=rhiccaDatWide$vzvStatus[j],cmvStatus_2levels=rhiccaDatWide$cmvStatus_2levels[j],vzvStatus_2levels=rhiccaDatWide$vzvStatus_2levels[j],eGFR_existingCKD=rhiccaDatWide$eGFR_existingCKD[j],category=unlist(cats)))
}

clinEventsTmp<-clinEventsTmp[!is.na(clinEventsTmp$category) & clinEventsTmp$category!="NA",]

#tmp<-rhiccaDatWide %>% dplyr::select(pid,crf.PLWH,crf.artnaive,crf.artRegimen.2levels,crf.gender,crf.age_group,cmvStatus,vzvStatus)
# for(j in 1:ncol(tmp)){tmp[,j]<-as.character(tmp[,j])}

# for(j in 1:nrow(clinEventsTmp)){
#   clinEventsTmp<-rbind(clinEventsTmp,unlist(c(clinEventsTmp[j,1:(ncol(clinEventsTmp)-1)],"Any")))
# }

tmpDeath<-rhiccaDatWide %>%
      dplyr::filter(pid %in% pidDeath) %>%
      dplyr::select(pid,crf.PLWH,crf.artnaive,crf.artRegimen.2levels,crf.gender,crf.age_group,cmvStatus,vzvStatus,cmvStatus_2levels,vzvStatus_2levels,eGFR_existingCKD)
colnames(tmpDeath)<-c("pid","ptype","artnaive","artRegimen","gender","age_group","cmvStatus","vzvStatus","cmvStatus_2levels","vzvStatus_2levels","eGFR_existingCKD")

clinEventsTmp<-cbind(
  rbind(
    clinEventsTmp[,-ncol(clinEventsTmp)],
    tmpDeath
  ),
  c(clinEventsTmp[,ncol(clinEventsTmp)],rep("Death",length(pidDeath)))
)

tmpCimt<-rhiccaDatWide %>%
      dplyr::filter(!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy") %>%
      dplyr::select(pid,crf.PLWH,crf.artnaive,crf.artRegimen.2levels,crf.gender,crf.age_group,cmvStatus,vzvStatus,cmvStatus_2levels,vzvStatus_2levels,eGFR_existingCKD)
colnames(tmpCimt)<-c("pid","ptype","artnaive","artRegimen","gender","age_group","cmvStatus","vzvStatus","cmvStatus_2levels","vzvStatus_2levels","eGFR_existingCKD")

tmpPwv<-rhiccaDatWide %>%
      dplyr::filter(!is.na(rhiccaDatWide$newOnsetPWV) & rhiccaDatWide$newOnsetPWV=="new PWV vasculopathy") %>%
      dplyr::select(pid,crf.PLWH,crf.artnaive,crf.artRegimen.2levels,crf.gender,crf.age_group,cmvStatus,vzvStatus,cmvStatus_2levels,vzvStatus_2levels,eGFR_existingCKD)
colnames(tmpPwv)<-c("pid","ptype","artnaive","artRegimen","gender","age_group","cmvStatus","vzvStatus","cmvStatus_2levels","vzvStatus_2levels","eGFR_existingCKD")

clinEventsTmp<-cbind(
  rbind(
    clinEventsTmp[,-ncol(clinEventsTmp)],
    tmpCimt,
    tmpPwv
  ),
  c(clinEventsTmp[,ncol(clinEventsTmp)],rep("CIMT",sum(!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy")),rep("PWV",sum(!is.na(rhiccaDatWide$newOnsetPWV) & rhiccaDatWide$newOnsetPWV=="new PWV vasculopathy")))
)

# for(pid in pidDeath){
#   clinEventsTmp<-rbind(clinEventsTmp,c(pid,unlist(as.character(tmp[tmp$pid==pid,c("crf.PLWH","crf.artnaive","crf.artRegimen.2levels","crf.gender","crf.age_group","cmvStatus","vzvStatus")])),"Death"))
# }
# for(pid in rhiccaDatWide$pid[!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy"]){
#   clinEventsTmp<-rbind(clinEventsTmp,c(pid,unlist(as.character(tmp[tmp$pid==pid,c("crf.PLWH","crf.artnaive","crf.artRegimen.2levels","crf.gender","crf.age_group","cmvStatus","vzvStatus")])),"CIMT"))
# }

colnames(clinEventsTmp)[ncol(clinEventsTmp)]<-"category"

clinEventsSystemic<-clinEventsTmp %>% dplyr::filter(category=="Systemic disease")

tt<-table(clinEventsTmp$ptype,clinEventsTmp$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[i]])/(1000*365.25))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}
 
ttPtype<-ttCount
 
#kable(ttCount,caption="Clinical events in participants, stratified by whether they are PLWH or controls. The number in brackets is the rate of events per 1,000 person-years.") %>%
#  kable_styling(full_width = FALSE)
tt<-table(clinEventsTmp$gender,clinEventsTmp$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.gender==rownames(tt)[i]])/(1000*365.25))
}

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}

ttSex<-ttCount

# kable(ttCount,caption="Clinical events stratified by sex. The number in brackets is the rate of events per 1,000 person-years.") %>%
#   kable_styling(full_width = FALSE)
tt<-table(clinEventsTmp$age_group,clinEventsTmp$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age_group==rownames(tt)[i]])/(1000*365.25))
}

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}

# kable(ttCount[rownames(ttCount)!="[0,35)",],caption="Clinical events stratified by age group. (All participants at least 35 years of age). The number in brackets is the rate of events per 1,000 person-years.") %>%
#   kable_styling(full_width = FALSE)

ttAgeGrp<-ttCount[rownames(ttCount)!="[0,35)",]
tt<-table(clinEventsTmp$cmvStatus,clinEventsTmp$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i]])/(1000*365.25))
}

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}

ttCount[ttCount=="0 (NaN)"]<-"0 (0)"

# kable(ttCount,caption="Clinical events stratified by CMV status. The number in brackets is the rate of events per 1,000 person-years.") %>%
#   kable_styling(full_width = FALSE)

ttCmv<-ttCount
tt<-table(clinEventsTmp$vzvStatus,clinEventsTmp$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i]])/(1000*365.25))
}

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}

# kable(ttCount,caption="Clinical events stratified by VZV status. The number in brackets is the rate of events per 1,000 person-years.") %>%
#   kable_styling(full_width = FALSE)

ttVzv<-ttCount
clinEventsTmpART<-clinEventsTmp %>% dplyr::filter(ptype=="PLWH")

tt<-table(clinEventsTmpART$artRegimen,clinEventsTmpART$category)
tt<-tt[,c("Death","Cancer","Infection","Systemic disease","Undetermined","CVD","CIMT","PWV")]
tt<-cbind(rowSums(tt[,!(colnames(tt) %in% c("Death","CIMT","PWV"))]),tt)
colnames(tt)[1]<-"Any clinical event"
colnames(tt)[ncol(tt)-1]<-"CVD (sub-clinical, CIMT)"
colnames(tt)[ncol(tt)]<-"CVD (sub-clinical, PWV)"
tt<-tt[,c(2,1,3:ncol(tt))]

ttCount<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$crf.artRegimen.2levels) & rhiccaDatWide$crf.artRegimen.2levels==rownames(tt)[i]])/(1000*365.25))
}

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}
  
# kable(ttCount,caption="Clinical events in PLWH, stratified by whether they are switched ART regimen to dolutegravir or not. The number in brackets is the rate of events per 1,000 person-years.") %>%
#   kable_styling(full_width = FALSE)

ttArt<-ttCount
tt<-rbind(
  ttPtype,
  ttSex,
  ttAgeGrp,
  ttCmv,
  ttVzv,
  ttArt
)

kable(tt,caption=" Clinical and sub-clinical events summarised by different participant characteristics. The numbers in brackets are the event rates per 1,000 person-years.") %>%
  kableExtra::kable_styling(full_width = FALSE) %>%
  kableExtra::pack_rows(start_row=1,end_row=2,group_label="Participant type") %>%
  kableExtra::pack_rows(start_row=3,end_row=4,group_label="Sex") %>%
  kableExtra::pack_rows(start_row=5,end_row=8,group_label="Age group") %>%
  kableExtra::pack_rows(start_row=9,end_row=12,group_label="CMV status") %>%
  kableExtra::pack_rows(start_row=13,end_row=16,group_label="VZV status") %>%
  kableExtra::pack_rows(start_row=17,end_row=18,group_label="PLWH only: ART regimen")
Table 9.1: Clinical and sub-clinical events summarised by different participant characteristics. The numbers in brackets are the event rates per 1,000 person-years.
Death Any clinical event Cancer Infection Systemic disease Undetermined CVD CVD (sub-clinical, CIMT) CVD (sub-clinical, PWV)
Participant type
Control 0 (0.000) 34 (82.831) 0 (0.000) 0 (0.000) 32 (77.958) 1 (2.436) 1 (2.436) 2 (4.872) 10 (24.362)
PLWH 37 (28.390) 100 (76.730) 5 (3.837) 27 (20.717) 57 (43.736) 3 (2.302) 8 (6.138) 9 (6.906) 11 (8.440)
Sex
Female 12 (17.184) 67 (95.945) 2 (2.864) 11 (15.752) 50 (71.601) 2 (2.864) 2 (2.864) 5 (7.160) 6 (8.592)
Male 25 (24.620) 67 (65.982) 3 (2.954) 16 (15.757) 39 (38.408) 2 (1.970) 7 (6.894) 6 (5.909) 15 (14.772)
Age group
[35,45) 13 (12.609) 61 (59.167) 3 (2.910) 12 (11.639) 41 (39.768) 3 (2.910) 2 (1.940) 1 (0.970) 7 (6.790)
[45,55) 16 (32.569) 49 (99.743) 1 (2.036) 10 (20.356) 34 (69.209) 1 (2.036) 3 (6.107) 2 (4.071) 9 (18.320)
[55,65) 6 (43.622) 12 (87.245) 0 (0.000) 3 (21.811) 6 (43.622) 0 (0.000) 3 (21.811) 5 (36.352) 3 (21.811)
[65,Inf) 2 (37.068) 12 (222.408) 1 (18.534) 2 (37.068) 8 (148.272) 0 (0.000) 1 (18.534) 3 (55.602) 2 (37.068)
CMV status
persistently low titres 4 (5.484) 32 (43.872) 0 (0.000) 4 (5.484) 25 (34.275) 1 (1.371) 2 (2.742) 7 (9.597) 11 (15.081)
progression to low titres 0 (0.000) 1 (45.486) 0 (0.000) 0 (0.000) 1 (45.486) 0 (0.000) 0 (0.000) 0 (0.000) 0 (0.000)
progression to high titres 1 (6.740) 13 (87.625) 1 (6.740) 0 (0.000) 12 (80.885) 0 (0.000) 0 (0.000) 2 (13.481) 1 (6.740)
persistently high titres 2 (10.143) 16 (81.145) 1 (5.072) 2 (10.143) 13 (65.931) 0 (0.000) 0 (0.000) 1 (5.072) 3 (15.215)
VZV status
persistently low titres 6 (8.101) 37 (49.958) 2 (2.700) 4 (5.401) 29 (39.157) 1 (1.350) 1 (1.350) 4 (5.401) 8 (10.802)
progression to low titres 0 (0.000) 7 (57.226) 0 (0.000) 1 (8.175) 6 (49.051) 0 (0.000) 0 (0.000) 1 (8.175) 2 (16.350)
progression to high titres 0 (0.000) 2 (42.669) 0 (0.000) 0 (0.000) 2 (42.669) 0 (0.000) 0 (0.000) 0 (0.000) 1 (21.335)
persistently high titres 1 (5.339) 16 (85.422) 0 (0.000) 1 (5.339) 14 (74.745) 0 (0.000) 1 (5.339) 5 (26.694) 4 (21.356)
PLWH only: ART regimen
ART: Change to dolutegravir 3 (4.112) 37 (50.713) 1 (1.371) 4 (5.482) 29 (39.748) 1 (1.371) 2 (2.741) 5 (6.853) 8 (10.965)
ART: No change to dolutegravir 34 (59.268) 63 (109.819) 4 (6.973) 23 (40.093) 28 (48.809) 2 (3.486) 6 (10.459) 4 (6.973) 3 (5.229)

10 Incidence rate of clinical and subclinical events are ~2-folds higher in PLWH.

In unadjusted analyses, shown in Table 10.1, we show that CVD clinical and sub-clinical CIMT event rates are higher in PLWH (though we lack power to determine that these differences are statistically significant), in particular event rates are 1.8 times higher (13.04 events per 1,000 person-years in PLWH compared to 7.31 in controls) when we consider clinical and sub-clinical events together. In the same table, we also show that pVZV is statistically significantly associated with clinical and sub-clinical events.

# idxCIMT<-which(!is.na(rhiccaDatWide$newOnsetCIMT) & rhiccaDatWide$newOnsetCIMT=="new CIMT vasculopathy")
# pidsCIMT<-rhiccaDatWide$pid[idxCIMT]   
# 
# tmp<-cbind(rhiccaDatWide %>% dplyr::filter(pid %in% pidsCIMT) %>% dplyr::select(c(pid,crf.PLWH,crf.artnaive,crf.artRegimen.2levels,crf.gender,crf.age_group,cmvStatus,vzvStatus)),"CVD (sub-clinical, CIMT)")
# colnames(tmp)<-colnames(clinEventsTmp)
# clinEventsTmp<-rbind(clinEventsTmp,tmp)

clinEventsTmp<-clinEventsTmp %>%
  dplyr::filter(category %in% c("CVD","CIMT","PWV"))

tt<-table(clinEventsTmp$category)
ttt<-data.frame(
  CVD.clinical=tt["CVD"],
  CVD.CIMT=tt["CIMT"],
  CVD.PWV=tt["PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
tt<-tt/sum(as.numeric(rhiccaDatWide$obsTime)/(1000*365.25))
ttLow=tt-qnorm(0.975)*sqrt(tt/sum(as.numeric(rhiccaDatWide$obsTime)/(1000*365.25)))
ttUpp=tt+qnorm(0.975)*sqrt(tt/sum(as.numeric(rhiccaDatWide$obsTime)/(1000*365.25)))

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

ttCountAll<-ttCount

tt<-table(clinEventsTmp$ptype,clinEventsTmp$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"],
  CVD.PWV=tt[,"PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[i]])/(1000*365.25))
  ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[i]])/(1000*365.25)))
  ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[i]])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

#ttTmp<-cbind(ttCountCount[,"CVD.clinical"],c(sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(rhiccaDatWide$crf.ptype==rownames(tt)[2]))-ttCountCount[,"CVD.clinical"])
#cvdClinicalFishP<-fisher.test(ttTmp)$p.value
cvdClinicalPoisP<-poisson.test(x=ttCountCount[,"CVD.clinical"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[1]])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[2]])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinical"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.clinical"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH!="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.clinical"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinical<-(totCases-hypoCases)/totCases

#ttTmp<-cbind(ttCountCount[,"CVD.CIMT"],c(sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(rhiccaDatWide$crf.ptype==rownames(tt)[2]))-ttCountCount[,"CVD.CIMT"])
#cvdCimtFishP<-fisher.test(ttTmp)$p.value
cvdCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.CIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[1]])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[2]])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.CIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.CIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH!="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.CIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafCimt<-(totCases-hypoCases)/totCases

# ttTmp<-cbind(ttCountCount[,"CVD.PWV"],c(sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(rhiccaDatWide$crf.ptype==rownames(tt)[2]))-ttCountCount[,"CVD.PWV"])
# cvdPwvFishP<-fisher.test(ttTmp)$p.value
cvdPwvPoisP<-poisson.test(x=ttCountCount[,"CVD.PWV"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[1]])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[2]])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.PWV"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.PWV"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH!="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.PWV"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafPwv<-(totCases-hypoCases)/totCases

# ttTmp<-cbind(ttCountCount[,"CVD.clinicalAndCIMT"],c(sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(rhiccaDatWide$crf.ptype==rownames(tt)[2]))-ttCountCount[,"CVD.clinicalAndCIMT"])
# cvdClinicalCimtFishP<-fisher.test(ttTmp)$p.value
cvdClinicalCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[1]])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[2]])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH!="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="PLWH","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases

# ttTmp<-cbind(ttCountCount[,"CVD.clinicalAndCIMTAndPWV"],c(sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(rhiccaDatWide$crf.ptype==rownames(tt)[2]))-ttCountCount[,"CVD.clinicalAndCIMTAndPWV"])
# cvdClinicalCimtPwvFishP<-fisher.test(ttTmp)$p.value
# cvdClinicalCimtPwvPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMTAndPWV"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[1]])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==rownames(tt)[2]])/(1000*365.25))))$p.value

# kable(ttCount,caption="CVD clinical and sub-clinical events in participants, stratified by whether they are PLWH or controls. The number in brackets is the rate of events per 1,000 person-years.",col.names=paste(sep=", Poisson test p = ",c("Clinical events","CIMT sub-clinical events","PWV sub-clinical events","Clinical & CIMT sub-clinical events","Clinical & CIMT & PWV sub-clinical events"),format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP,cvdClinicalCimtPwvPoisP))))) %>%
#   kable_styling(full_width = FALSE)

# rownames(ttCount)[rownames(ttCount)=="Patient"]<-"PLWH"

ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson test p = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP))),", PAF = ",format(nsmall=3,round(digits=3,c(pafClinical,pafCimt,pafPwv,pafClinCimt)))),ttCount)
clinEventsTmp<-clinEventsTmp %>%
  dplyr::mutate(
    age_group_2lvls=case_when(
      age_group %in% c("[35,45)","[45,55)") ~ "<55",
      age_group %in% c("[55,65)","[65,Inf)") ~ "55+"
    )
  )

tt<-table(clinEventsTmp$age_group_2lvls,clinEventsTmp$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"],
  CVD.PWV=tt[,"PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  if(i==1){
    tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25))
    ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)))
    ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)))
  }else if(i==2){
    tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))
    ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25)))
    ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25)))
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(rownames(ttCount)[i]=="<55"){
      airCvdUnder55=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
    }
    if(rownames(ttCount)[i]=="55+"){
      airCvdAbove55=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
    }
  }
}

cvdClinicalPoisP<-poisson.test(x=ttCountCount[,"CVD.clinical"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinical"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinical"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinical"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))
pafClinical<-(totCases-hypoCases)/totCases

cvdCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.CIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.CIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.CIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.CIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))
pafCimt<-(totCases-hypoCases)/totCases

cvdPwvPoisP<-poisson.test(x=ttCountCount[,"CVD.PWV"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.PWV"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.PWV"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.PWV"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))
pafPwv<-(totCases-hypoCases)/totCases

cvdClinicalCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases

ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson test p = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP))),", PAF = ",format(nsmall=3,round(digits=3,c(pafClinical,pafCimt,pafPwv,pafClinCimt)))),ttCount)
pidsWithVzv<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$vzvStatus)]
clinEventsTmp2<-clinEventsTmp %>%
  dplyr::filter(pid %in% pidsWithVzv) %>%
  dplyr::mutate(vzvStatus_2levels=ifelse(vzvStatus=="persistently high titres","persistently high titres","not persistently high titres"))

tt<-table(clinEventsTmp2$vzvStatus,clinEventsTmp2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"],
  CVD.PWV=tt[,"PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i]])/(1000*365.25))
    ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i]])/(1000*365.25)))
    ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i]])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

modClinEventsConfirmedCVD.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsCIMTonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCIMTonly~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsPWVonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantPWVonly~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable.2levels<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~vzvStatus_2levels,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
# modClinEventsConfirmedCVDwithCIMTPWV.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMTPWV~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))

cvdClinicalPoisP<-summary(pool(modClinEventsConfirmedCVD.univariable))$p.value[summary(pool(modClinEventsConfirmedCVD.univariable))$term=="vzvStatuspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.clinical"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinical"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinical"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
pafClinical<-(totCases-hypoCases)/totCases

cvdCimtPoisP<-summary(pool(modClinEventsCIMTonly.univariable))$p.value[summary(pool(modClinEventsCIMTonly.univariable))$term=="vzvStatuspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.CIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.CIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.CIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
pafCimt<-(totCases-hypoCases)/totCases

cvdPwvPoisP<-summary(pool(modClinEventsPWVonly.univariable))$p.value[summary(pool(modClinEventsPWVonly.univariable))$term=="vzvStatuspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.PWV"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.PWV"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.PWV"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
pafPwv<-(totCases-hypoCases)/totCases

cvdClinicalCimtPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$term=="vzvStatuspersistently high titres"]
cvdClinicalCimtPoisP.2levels<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$term=="vzvStatus_2levelspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres"])/(1000*365.25))
incExp<-sum(ttCountCount[rownames(ttCountCount)=="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
incOverall<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus)])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases

# cvdClinicalCimtPwvPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMTPWV.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMTPWV.univariable))$term=="vzvStatuspersistently high titres"]

# cvdClinicalPoisP<-poisson.test(x=ttCountCount[,"CVD.clinical"],T=c(sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[2])))$p.value
# cvdCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.CIMT"],T=c(sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[2])))$p.value
# cvdPwvPoisP<-poisson.test(x=ttCountCount[,"CVD.PWV"],T=c(sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[2])))$p.value
# cvdClinicalCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMT"],T=c(sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[2])))$p.value
# cvdClinicalCimtPwvPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMTAndPWV"],T=c(!is.na(rhiccaDatWide$vzvStatus) & sum(rhiccaDatWide$crf.ptype==rownames(tt)[1]),sum(!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.ptype==rownames(tt)[2])))$p.value

# kable(ttCount,caption="CVD clinical and sub-clinical events in participants, stratified by whether VZV status. The number in brackets is the rate of events per 1,000 person-years.",col.names=paste(sep=", Poisson regression p-value for persistently high titres = ",c("Clinical events","CIMT sub-clinical events","PWV sub-clinical events","Clinical & CIMT sub-clinical events","Clinical & CIMT & PWV sub-clinical events"),format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP,cvdClinicalCimtPwvPoisP))))) %>%
#   kable_styling(full_width = FALSE)

ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson regression p-value for persistently high VZV = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP))),", PAF = ",format(nsmall=3,round(digits=3,c(pafClinical,pafCimt,pafPwv,pafClinCimt)))),ttCount)
tt<-table(clinEventsTmp2$vzvStatus_2levels,clinEventsTmp2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"],
  CVD.PWV=tt[,"PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i]])/(1000*365.25))
    ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i]])/(1000*365.25)))
    ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i]])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    if(rownames(ttCount)[i]=="not persistently high titres"){
      airCvdNotpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    if(rownames(ttCount)[i]=="persistently high titres"){
      airCvdpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
  }
}
pidsWithCmv<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$cmvStatus)]
clinEventsTmp2<-clinEventsTmp %>% dplyr::filter(pid %in% pidsWithCmv)

tt<-table(clinEventsTmp2$cmvStatus,clinEventsTmp2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"],
  CVD.PWV=tt[,"PWV"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i]])/(1000*365.25))
  ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i]])/(1000*365.25)))
  ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i]])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttLow[i,ttLow[i,]<0]<-0
    
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

#ttCount<-ttCount[-which(grepl(pattern="NaN",ttCount[,1])),]

modClinEventsConfirmedCVD.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsCIMTonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCIMTonly~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsPWVonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantPWVonly~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
# modClinEventsConfirmedCVDwithCIMTPWV.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMTPWV~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))

cvdClinicalPoisP<-summary(pool(modClinEventsConfirmedCVD.univariable))$p.value[summary(pool(modClinEventsConfirmedCVD.univariable))$term=="cmvStatuspersistently high titres"]
cvdCimtPoisP<-summary(pool(modClinEventsCIMTonly.univariable))$p.value[summary(pool(modClinEventsCIMTonly.univariable))$term=="cmvStatuspersistently high titres"]
cvdPwvPoisP<-summary(pool(modClinEventsPWVonly.univariable))$p.value[summary(pool(modClinEventsPWVonly.univariable))$term=="cmvStatuspersistently high titres"]
cvdClinicalCimtPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$term=="cmvStatuspersistently high titres"]
# cvdClinicalCimtPwvPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMTPWV.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMTPWV.univariable))$term=="cmvStatuspersistently high titres"]

# kable(ttCount,caption="CVD clinical and sub-clinical events in participants, stratified by whether CMV status. The number in brackets is the rate of events per 1,000 person-years.",col.names=paste(sep=", Poisson regression p-value for persistently high titres = ",c("Clinical events","CIMT sub-clinical events","PWV sub-clinical events","Clinical & CIMT sub-clinical events","Clinical & CIMT & PWV sub-clinical events"),format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP,cvdClinicalCimtPwvPoisP))))) %>%
#   kable_styling(full_width = FALSE)

rownames(ttCount)<-paste(sep="",rownames(ttCount)," ")
ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson regression p-value for persistently high CMV = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdPwvPoisP,cvdClinicalCimtPoisP)))),ttCount)
counter<-1
for(j in 1:nrow(ttCountAll)){
  if(grepl(rownames(ttCountAll)[j],pattern="[0-9]")){
    if(!(rownames(ttCountAll)[j] %in% c("<55","55+"))){
      rownames(ttCountAll)[j]<-paste(collapse="",rep(" ",counter-1))
      counter<-counter+1
    }
  }
}
rownames(ttCountAll)[1]<-paste(collapse="",rep(" ",counter-1))
rm(counter)

kable(ttCountAll,caption="CVD clinical and sub-clinical events in participants. The number in brackets is the rate of events per 1,000 person-years.",col.names=c("Clinical events","CIMT sub-clinical events","PWV sub-clinical events","Clinical & CIMT sub-clinical events")) %>%
  kable_styling(full_width = FALSE) %>%
  pack_rows(start_row=1,end_row=1,group_label="All participants.") %>%
  pack_rows(start_row=2,end_row=4,group_label="Stratified by participant type.") %>%
  pack_rows(start_row=5,end_row=7,group_label="Stratified by age group.") %>%
  pack_rows(start_row=8,end_row=12,group_label="Stratified by VZV titres.") %>%
  pack_rows(start_row=13,end_row=17,group_label="Stratified by CMV titres.")
Table 10.1: CVD clinical and sub-clinical events in participants. The number in brackets is the rate of events per 1,000 person-years.
Clinical events CIMT sub-clinical events PWV sub-clinical events Clinical & CIMT sub-clinical events
All participants.
9 (5.252, 95% CI [1.821, 8.683]) 11 (6.419, 95% CI [ 2.626, 10.212]) 21 (12.254, 95% CI [ 7.013, 17.495]) 20 (11.670, 95% CI [ 6.556, 16.785])
Stratified by participant type.
Poisson test p = 0.696, PAF = 0.536 Poisson test p = 1.000, PAF = 0.241 Poisson test p = 0.018, PAF = -0.988 Poisson test p = 0.441, PAF = 0.374
Control 1 (2.436, 95% CI [0.000, 7.211]) 2 (4.872, 95% CI [ 0.000, 11.625]) 10 (24.362, 95% CI [ 9.263, 39.461]) 3 (7.309, 95% CI [ 0.000, 15.579])
PLWH 8 (6.138, 95% CI [ 1.885, 10.392]) 9 (6.906, 95% CI [ 2.394, 11.417]) 11 (8.440, 95% CI [ 3.452, 13.428]) 17 (13.044, 95% CI [ 6.843, 19.245])
Stratified by age group.
Poisson test p = 0.012, PAF = 0.375 Poisson test p = 0.000, PAF = 0.693 Poisson test p = 0.077, PAF = 0.142 Poisson test p = 0.000, PAF = 0.550
<55 5 (3.285, 95% CI [0.406, 6.164]) 3 (1.971, 95% CI [0.000, 4.201]) 16 (10.511, 95% CI [ 5.361, 15.661]) 8 (5.255, 95% CI [1.614, 8.897])
55+ 4 (20.888, 95% CI [ 0.418, 41.358]) 8 (41.776, 95% CI [12.827, 70.724]) 5 (26.110, 95% CI [ 3.224, 48.996]) 12 (62.664, 95% CI [27.209, 98.118])
Stratified by VZV titres.
Poisson regression p-value for persistently high VZV = 0.827, PAF = 0.397 Poisson regression p-value for persistently high VZV = 0.007, PAF = 0.397 Poisson regression p-value for persistently high VZV = 0.334, PAF = 0.116 Poisson regression p-value for persistently high VZV = 0.025, PAF = 0.397
persistently low titres 1 (1.350, 95% CI [0.000, 3.997]) 4 (5.401, 95% CI [ 0.108, 10.694]) 8 (10.802, 95% CI [ 3.317, 18.287]) 5 (6.751, 95% CI [ 0.834, 12.669])
progression to low titres 0 (0.000, 95% CI [0.000, 0.000]) 1 (8.175, 95% CI [ 0.000, 24.198]) 2 (16.350, 95% CI [ 0.000, 39.010]) 1 (8.175, 95% CI [ 0.000, 24.198])
progression to high titres 0 (0.000, 95% CI [0.000, 0.000]) 0 (0.000, 95% CI [0.000, 0.000]) 1 (21.335, 95% CI [ 0.000, 63.150]) 0 (0.000, 95% CI [0.000, 0.000])
persistently high titres 1 (5.339, 95% CI [ 0.000, 15.803]) 5 (26.694, 95% CI [ 3.296, 50.093]) 4 (21.356, 95% CI [ 0.427, 42.284]) 6 (32.033, 95% CI [ 6.402, 57.665])
Stratified by CMV titres.
Poisson regression p-value for persistently high CMV = 0.947 Poisson regression p-value for persistently high CMV = 0.974 Poisson regression p-value for persistently high CMV = 0.484 Poisson regression p-value for persistently high CMV = 0.927
persistently low titres 2 (2.742, 95% CI [0.000, 6.542]) 7 (9.597, 95% CI [ 2.488, 16.707]) 11 (15.081, 95% CI [ 6.169, 23.993]) 9 (12.339, 95% CI [ 4.278, 20.400])
progression to low titres 0 (0.000, 95% CI [0.000, 0.000]) 0 (0.000, 95% CI [0.000, 0.000]) 0 (0.000, 95% CI [0.000, 0.000]) 0 (0.000, 95% CI [0.000, 0.000])
progression to high titres 0 (0.000, 95% CI [0.000, 0.000]) 2 (13.481, 95% CI [ 0.000, 32.164]) 1 (6.740, 95% CI [ 0.000, 19.951]) 2 (13.481, 95% CI [ 0.000, 32.164])
persistently high titres 0 (0.000, 95% CI [0.000, 0.000]) 1 (5.072, 95% CI [ 0.000, 15.012]) 3 (15.215, 95% CI [ 0.000, 32.432]) 1 (5.072, 95% CI [ 0.000, 15.012])
tmp<-clinEventsTmp %>% dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")
tt<-table(tmp$age_group_2lvls,tmp$category)
ttt<-data.frame(
  CVD.clinical=ifelse("CVD" %in% colnames(tt),tt[,"CVD"],0),
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  if(i==1){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  }else if(i==2){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="<55"){
        airCvdUnder55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="55+"){
        airCvdAbove55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}
tmp<-clinEventsTmp %>%
  dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")

tt<-table(tmp$gender,tmp$category)
ttt<-data.frame(
  CVD.clinical=ifelse("CVD" %in% colnames(tt),tt[,"CVD"],0),
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.gender==rownames(ttCount)[i] & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="Female"){
        airCvdFemalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="Male"){
        airCvdMalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}

The absolute risk (expressed as an incidence rate) of clinical and sub-clinical CIMT events is 32.033, 95% CI [ 6.402, 57.665] per 1,000 person-years in participants with pVZV compared to 6.595, 95% CI [ 1.318, 11.872] per 1,000 person-years in those without pVZV (Poisson p-value for this difference p=0.026).

We can also express this in terms of 2-, 5- and 10-year risk. For this we make use of the cumulative distribution function of the Poisson distribution, using the above reported incidence rates and their associated 95% CIs. The Poisson test p-value for the difference in risk remains of course the same, regardless how the risk is reported.

The absolute risk (expressed as the probability of 1 or more events within the next 10 years; in other words the 10-year risk) of clinical and sub-clinical CIMT events is 27.41%, 95% CI [ 6.20%, 43.82%] in participants with pVZV compared to 6.38%, 95% CI [ 1.31%, 11.19%] in those without pVZV.

The absolute risk (expressed as the probability of 1 or more events within the next 5 years; in other words the 5-year risk) of clinical and sub-clinical CIMT events is 14.80%, 95% CI [ 3.15%, 25.05%] in participants with pVZV compared to 3.24%, 95% CI [0.66%, 5.76%] in those without pVZV.

The absolute risk (expressed as the probability of 1 or more events within the next 2 years; in other words the 2-year risk) of clinical and sub-clinical CIMT events is 6.21%, 95% CI [ 1.27%, 10.89%] in participants with pVZV compared to 1.31%, 95% CI [0.26%, 2.35%] in those without pVZV.

We see the association with pVZV also in minimally and fully adjusted models, though it is only borderline significant (Table 10.4).

The absolute risk (expressed as the probability of 1 or more events within the next 10 years; in other words the 10-year risk) of clinical and sub-clinical CIMT events is 46.56%, 95% CI [23.82%, 62.51%] in participants aged 55 and above compared to 5.12%, 95% CI [1.60%, 8.51%] in those below 55 years of age.

The absolute risk (expressed as the probability of 1 or more events within the next 5 years; in other words the 5-year risk) of clinical and sub-clinical CIMT events is 26.90%, 95% CI [12.72%, 38.77%] in participants aged 55 and above compared to 2.59%, 95% CI [0.80%, 4.35%] in those below 55 years of age.

The absolute risk (expressed as the probability of 1 or more events within the next 2 years; in other words the 2-year risk) of clinical and sub-clinical CIMT events is 11.78%, 95% CI [ 5.30%, 17.82%] in participants aged 55 and above compared to 1.05%, 95% CI [0.32%, 1.76%] in those below 55 years of age.

df<-data.frame(
  idx=1:6,
  pVZV=c("-",rep("+",5)),
  Grouping=factor(c(rep("All participants",2),rep("Age",2),rep("Sex",2)),levels=c("All participants","Age","Sex")),
  Characteristic=c(rep("",2),"<55","55+","Female","Male"),
  ir=c(as.numeric(strsplit(airCvdNotpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdUnder55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdAbove55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdFemalepVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdMalepVZV,split=",")[[1]][1])),
  irLow=c(as.numeric(strsplit(strsplit(airCvdNotpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdUnder55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdAbove55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdFemalepVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdMalepVZV,split=",")[[1]][2],split="\\[")[[1]][2])),
  irUpp=c(as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdNotpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdUnder55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdAbove55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdFemalepVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdMalepVZV,split=",")[[1]][3]))),
  arFullCI=gsub(pattern="\\[ ",replacement="\\[",gsub(pattern=", 95% CI",replacement="",paste(sep="","AR ",c(
    ar2CvdNotpVZV,
    ar2CvdpVZV,
    ar2CvdUnder55pVZV,
    ar2CvdAbove55pVZV,
    ar2CvdFemalepVZV,
    ar2CvdMalepVZV
  ))))
) %>%
  dplyr::mutate(
    irFullCI=paste(sep="","IR ",format(nsmall=1,round(digits=1,ir))," [",format(nsmall=1,round(digits=1,irLow)),",",format(nsmall=1,round(digits=1,irUpp)),"]")
  )

gIrAll<-ggplot() +
  geom_bar(data=df,mapping=aes(x=idx,y=ir,fill=Grouping),stat="identity") +
  #geom_errorbar(data=df,mapping=aes(x=idx,y=ir,ymin=irLow,ymax=irUpp),width=0.1,alpha=0.75,lwd=0.4,col="darkgrey") +
  geom_text(data=df,mapping=aes(x=idx,y=ir+3.25,label=irFullCI),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(x=idx,y=ir,label=gsub(pattern=", ",replacement="",arFullCI)),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(label=pVZV,x=idx),y=-5,size=8) +
  geom_text(data=data.frame(lbl=c(rep("",2),"<55","55+","Female","Male"),x=1:6,col=df$Grouping),mapping=aes(label=lbl,x=x,col=col),y=-12,size=4) +
  geom_text(data=data.frame(lbl=factor(levels(df$Grouping),levels=levels(df$Grouping)),x=seq(1.5,5.5,by=2)),mapping=aes(label=lbl,x=x,col=lbl),y=-20,size=6) +
  geom_text(data=data.frame(lbl=c("-  no pVZV","+ pVZV"), x=c(1,1), y=c(105,110)), mapping=aes(x=x,y=y,label=lbl), size=5, hjust=0) +
  #geom_text(data=data.frame(x=4,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  scale_fill_manual(values=c("steelblue","orange","#2E8B57")) +
  scale_color_manual(values=c("steelblue","orange","#2E8B57")) +
  coord_cartesian(ylim=c(-18,110)) +
  ylim(-25,1000) +
  theme_minimal() +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(),panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16)) +
  guides(color=FALSE,fill=FALSE) +
  ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)") +
  xlab("")

print(gIrAll)

pdf(width=8,height=8,file=paste(sep="_",outPrefix,"CIMT_CVDevents_FigureIncidenceRates_ALL_barplot.pdf"))
print(gIrAll)
dev.off()
## quartz_off_screen 
##                 2

We now repeat this for PLWH only.

clinEventsTmpPLWH<-clinEventsTmp %>%
  dplyr::filter(ptype=="PLWH")

tt<-table(clinEventsTmpPLWH$category)
ttt<-data.frame(
  CVD.clinical=tt["CVD"],
  CVD.CIMT=tt["CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt

nEvents<-unlist(tt)
tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))

tt<-nEvents/tObs
ttLow<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
ttUpp<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
# tt<-tt/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
# ttLow=tt-qnorm(0.975)*sqrt(tt/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
# ttUpp=tt+qnorm(0.975)*sqrt(tt/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))

tt<-t(as.matrix(tt))
ttLow<-t(as.matrix(ttLow))
ttUpp<-t(as.matrix(ttUpp))

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

ttCountAll<-ttCount
tt<-table(clinEventsTmpPLWH$age_group_2lvls,clinEventsTmpPLWH$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  if(i==1){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
    # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
    # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
    # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  }else if(i==2){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))

    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
    # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
    # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
    # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(rownames(ttCount)[i]=="<55"){
      airCvdUnder55=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdUnder55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
    }
    if(rownames(ttCount)[i]=="55+"){
      airCvdAbove55=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdAbove55=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
    }
  }
}

cvdClinicalPoisP<-poisson.test(x=ttCountCount[,"CVD.clinical"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinical"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinical"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinical"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinical<-(totCases-hypoCases)/totCases

cvdCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.CIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.CIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.CIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.CIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafCimt<-(totCases-hypoCases)/totCases

cvdClinicalCimtPoisP<-poisson.test(x=ttCountCount[,"CVD.clinicalAndCIMT"],T=c(sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)),sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))))$p.value

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="55+","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases

ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson test p = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdClinicalCimtPoisP))),", PAF = ",format(nsmall=3,round(digits=3,c(pafClinical,pafCimt,pafClinCimt)))),ttCount)
tmp<-clinEventsTmpPLWH %>% dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")
tt<-table(tmp$age_group_2lvls,tmp$category)
ttt<-data.frame(
  CVD.clinical=ifelse("CVD" %in% colnames(tt),tt[,"CVD"],0),
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  if(i==1){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
    # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    # #nEvents<-
    # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(log(tt[i,])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
    # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
  }else if(i==2){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
    # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
    # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="<55"){
        airCvdUnder55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="55+"){
        airCvdAbove55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}
tmp<-clinEventsTmpPLWH %>%
  dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")

tt<-table(tmp$gender,tmp$category)
ttt<-data.frame(
  CVD.clinical=ifelse("CVD" %in% colnames(tt),tt[,"CVD"],0),
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.gender==rownames(ttCount)[i] & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
    # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    # #nEvents<-
    # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(log(tt[i,])/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
    # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="PLWH" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="Female"){
        airCvdFemalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="Male"){
        airCvdMalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}
pidsWithVzv<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$vzvStatus)]
clinEventsTmpPLWH2<-clinEventsTmpPLWH %>%
  dplyr::filter(pid %in% pidsWithVzv) %>%
  dplyr::mutate(vzvStatus_2levels=ifelse(vzvStatus=="persistently high titres","persistently high titres","not persistently high titres"))

tt<-table(clinEventsTmpPLWH2$vzvStatus,clinEventsTmpPLWH2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  nEvents<-unlist(tt[i,])
  tObs<-sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  
  tt[i,]<-nEvents/tObs
  ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
  ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  #   ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  #   ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

modClinEventsConfirmedCVD.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVD~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsCIMTonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCIMTonly~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVDwithCIMT~vzvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable.2levels<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVDwithCIMT~vzvStatus_2levels,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))

cvdClinicalPoisP<-summary(pool(modClinEventsConfirmedCVD.univariable))$p.value[summary(pool(modClinEventsConfirmedCVD.univariable))$term=="vzvStatuspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.clinical"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinical"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinical"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres"])/(1000*365.25))
pafClinical<-(totCases-hypoCases)/totCases

cvdCimtPoisP<-summary(pool(modClinEventsCIMTonly.univariable))$p.value[summary(pool(modClinEventsCIMTonly.univariable))$term=="vzvStatuspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.CIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.CIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.CIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafCimt<-(totCases-hypoCases)/totCases

# cvdPwvPoisP<-summary(pool(modClinEventsPWVonly.univariable))$p.value[summary(pool(modClinEventsPWVonly.univariable))$term=="vzvStatuspersistently high titres"]
cvdClinicalCimtPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$term=="vzvStatuspersistently high titres"]
cvdClinicalCimtPoisP.2levels<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$term=="vzvStatus_2levelspersistently high titres"]

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
incExp<-sum(ttCountCount[rownames(ttCountCount)=="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
incOverall<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases
se<-sqrt(incNonExp/sum(rownames(ttCountCount)!="persistently high titres"))
incNonExpL<-incNonExp-qnorm(0.975)*se
incNonExpU<-incNonExp+qnorm(0.975)*se
hypoCasesL<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])+incNonExpL*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCasesU<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])+incNonExpU*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinCimtL<-(totCases-hypoCasesU)/totCases
pafClinCimtU<-(totCases-hypoCasesL)/totCases

ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson regression p-value for persistently high VZV = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdClinicalCimtPoisP))),", PAF = ",format(nsmall=3,round(digits=3,c(pafClinical,pafCimt,pafClinCimt)))),ttCount)
tt<-table(clinEventsTmpPLWH2$vzvStatus_2levels,clinEventsTmpPLWH2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  nEvents<-unlist(tt[i,])
  tObs<-sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  
  tt[i,]<-nEvents/tObs
  ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
  ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  #   ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  #   ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    if(rownames(ttCount)[i]=="not persistently high titres"){
      airCvdNotpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    if(rownames(ttCount)[i]=="persistently high titres"){
      airCvdpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
  }
}
tt<-table(clinEventsTmpPLWH2$gender,clinEventsTmpPLWH2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  nEvents<-unlist(tt[i,])
  tObs<-sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$crf.gender) & rhiccaDatWide$crf.gender==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  
  tt[i,]<-nEvents/tObs
  ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
  ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$crf.gender) & rhiccaDatWide$crf.gender==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  #   ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$crf.gender) & rhiccaDatWide$crf.gender==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  #   ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$crf.gender) & rhiccaDatWide$crf.gender==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    if(rownames(ttCount)[i]=="Female"){
      airCvdFemale=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdFemale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdFemale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdFemale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    if(rownames(ttCount)[i]=="Male"){
      airCvdMale=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdMale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdMale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdMale=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
  }
}
pidsWithCmv<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$cmvStatus)]
clinEventsTmpPLWH2<-clinEventsTmpPLWH %>% dplyr::filter(pid %in% pidsWithCmv)

tt<-table(clinEventsTmpPLWH2$cmvStatus,clinEventsTmpPLWH2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  nEvents<-unlist(tt[i,])
  tObs<-sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  
  tt[i,]<-nEvents/tObs
  ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
  ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  # tt[i,]<-tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
  # ttLow[i,]=tt[i,]-qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
  # ttUpp[i,]=tt[i,]+qnorm(0.975)*sqrt(tt[i,]/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$cmvStatus) & rhiccaDatWide$cmvStatus==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25)))
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}

#ttCount<-ttCount[-which(grepl(pattern="NaN",ttCount[,1])),]

modClinEventsConfirmedCVD.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVD~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsCIMTonly.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCIMTonly~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))
modClinEventsConfirmedCVDwithCIMT.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVDwithCIMT~cmvStatus,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))

cvdClinicalPoisP<-summary(pool(modClinEventsConfirmedCVD.univariable))$p.value[summary(pool(modClinEventsConfirmedCVD.univariable))$term=="cmvStatuspersistently high titres"]
cvdCimtPoisP<-summary(pool(modClinEventsCIMTonly.univariable))$p.value[summary(pool(modClinEventsCIMTonly.univariable))$term=="cmvStatuspersistently high titres"]
cvdClinicalCimtPoisP<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable))$term=="cmvStatuspersistently high titres"]

rownames(ttCount)<-paste(sep="",rownames(ttCount)," ")
ttCountAll<-rbind(ttCountAll,paste(sep="","Poisson regression p-value for persistently high CMV = ",format(nsmall=3,round(digits=3,c(cvdClinicalPoisP,cvdCimtPoisP,cvdClinicalCimtPoisP)))),ttCount)
counter<-1
for(j in 1:nrow(ttCountAll)){
  if(grepl(rownames(ttCountAll)[j],pattern="[0-9]")){
    if(!(rownames(ttCountAll)[j] %in% c("<55","55+"))){
      rownames(ttCountAll)[j]<-paste(collapse="",rep(" ",counter-1))
      counter<-counter+1
    }
  }
}
#rownames(ttCountAll)[1]<-paste(collapse="",rep(" ",counter-1))
rm(counter)

kable(ttCountAll,caption="CVD clinical and sub-clinical events in PLWH. The number in brackets is the rate of events per 1,000 person-years.",col.names=c("Clinical events","CIMT sub-clinical events","Clinical & CIMT sub-clinical events")) %>%
  kable_styling(full_width = FALSE) %>%
  pack_rows(start_row=1,end_row=1,group_label="All participants.") %>%
  pack_rows(start_row=2,end_row=4,group_label="Stratified by age group.") %>%
  pack_rows(start_row=5,end_row=9,group_label="Stratified by VZV titres.") %>%
  pack_rows(start_row=10,end_row=14,group_label="Stratified by CMV titres.")
Table 10.2: CVD clinical and sub-clinical events in PLWH. The number in brackets is the rate of events per 1,000 person-years.
Clinical events CIMT sub-clinical events Clinical & CIMT sub-clinical events
All participants.
CVD 8 (6.138, 95% CI [ 2.650, 12.095]) 9 (6.906, 95% CI [ 3.158, 13.109]) 17 (13.044, 95% CI [ 7.599, 20.885])
Stratified by age group.
Poisson test p = 0.029, PAF = 0.313 Poisson test p = 0.000, PAF = 0.634 Poisson test p = 0.000, PAF = 0.483
<55 5 (4.217, 95% CI [1.369, 9.841]) 3 (2.530, 95% CI [0.522, 7.394]) 8 (6.747, 95% CI [ 2.913, 13.294])
55+ 3 (25.519, 95% CI [ 5.263, 74.578]) 6 (51.039, 95% CI [ 18.730, 111.090]) 9 (76.558, 95% CI [ 35.007, 145.331])
Stratified by VZV titres.
Poisson regression p-value for persistently high VZV = 0.996, PAF = -0.206 Poisson regression p-value for persistently high VZV = 0.004, PAF = 0.540 Poisson regression p-value for persistently high VZV = 0.054, PAF = 0.455
persistently low titres 1 (1.787, 95% CI [0.045, 9.957]) 2 (3.574, 95% CI [ 0.433, 12.911]) 3 (5.361, 95% CI [ 1.106, 15.667])
progression to low titres 0 (0.000, 95% CI [ 0.000, 35.734]) 1 (9.687, 95% CI [ 0.245, 53.973]) 1 (9.687, 95% CI [ 0.245, 53.973])
progression to high titres 0 (0.000, 95% CI [ 0.000, 82.377]) 0 (0.000, 95% CI [ 0.000, 82.377]) 0 (0.000, 95% CI [ 0.000, 82.377])
persistently high titres 0 (0.000, 95% CI [ 0.000, 22.989]) 5 (31.160, 95% CI [10.118, 72.717]) 5 (31.160, 95% CI [10.118, 72.717])
Stratified by CMV titres.
Poisson regression p-value for persistently high CMV = 0.990 Poisson regression p-value for persistently high CMV = 0.938 Poisson regression p-value for persistently high CMV = 0.945
persistently low titres 1 (1.960, 95% CI [ 0.050, 10.922]) 5 (9.801, 95% CI [ 3.182, 22.873]) 6 (11.761, 95% CI [ 4.316, 25.600])
progression to low titres 0 (0.000, 95% CI [ 0.000, 167.791]) 0 (0.000, 95% CI [ 0.000, 167.791]) 0 (0.000, 95% CI [ 0.000, 167.791])
progression to high titres 0 (0.000, 95% CI [ 0.000, 26.102]) 2 (14.152, 95% CI [ 1.714, 51.121]) 2 (14.152, 95% CI [ 1.714, 51.121])
persistently high titres 0 (0.000, 95% CI [ 0.000, 19.218]) 1 (5.210, 95% CI [ 0.132, 29.027]) 1 (5.210, 95% CI [ 0.132, 29.027])

The absolute risk (expressed as an incidence rate) of clinical and sub-clinical CIMT events is 31.160, 95% CI [10.118, 72.717] per 1,000 person-years in PLWH with pVZV compared to 5.653, 95% CI [ 1.540, 14.474] per 1,000 person-years in those without pVZV (Poisson p-value for this difference p=0.057).

We can also express this in terms of 2-, 5- and 10-year risk. For this we make use of the cumulative distribution function of the Poisson distribution, using the above reported incidence rates and their associated 95% CIs. The Poisson test p-value for the difference in risk remains of course the same, regardless how the risk is reported.

The absolute risk (expressed as the probability of 1 or more events within the next 10 years; in other words the 10-year risk) of clinical and sub-clinical CIMT events is 26.77%, 95% CI [ 9.62%, 51.67%] in PLWH with pVZV compared to 5.50%, 95% CI [ 1.53%, 13.47%] in those without pVZV.

The absolute risk (expressed as the probability of 1 or more events within the next 5 years; in other words the 5-year risk) of clinical and sub-clinical CIMT events is 14.43%, 95% CI [ 4.93%, 30.48%] in PLWH with pVZV compared to 2.79%, 95% CI [0.77%, 6.98%] in those without pVZV.

The absolute risk (expressed as the probability of 1 or more events within the next 2 years; in other words the 2-year risk) of clinical and sub-clinical CIMT events is 6.04%, 95% CI [ 2.00%, 13.54%] in PLWH with pVZV compared to 1.12%, 95% CI [0.31%, 2.85%] in those without pVZV.

The absolute risk (expressed as the probability of 1 or more events within the next 10 years; in other words the 10-year risk) of clinical and sub-clinical CIMT events is 53.49%, 95% CI [29.54%, 76.62%] in PLWH aged 55 and above compared to 6.52%, 95% CI [ 2.87%, 12.45%] in those below 55 years of age.

The absolute risk (expressed as the probability of 1 or more events within the next 5 years; in other words the 5-year risk) of clinical and sub-clinical CIMT events is 31.80%, 95% CI [16.06%, 51.65%] in PLWH aged 55 and above compared to 3.32%, 95% CI [1.45%, 6.43%] in those below 55 years of age.

The absolute risk (expressed as the probability of 1 or more events within the next 2 years; in other words the 2-year risk) of clinical and sub-clinical CIMT events is 14.20%, 95% CI [ 6.76%, 25.22%] in PLWH aged 55 and above compared to 1.34%, 95% CI [0.58%, 2.62%] in those below 55 years of age.

df<-data.frame(
  idx=1:6,
  pVZV=c("-",rep("+",5)),
  Grouping=factor(c(rep("All PLWH",2),rep("Age",2),rep("Sex",2)),levels=c("All PLWH","Age","Sex")),
  Characteristic=c(rep("",2),"<55","55+","Female","Male"),
  ir=c(as.numeric(strsplit(airCvdNotpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdUnder55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdAbove55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdFemalepVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdMalepVZV,split=",")[[1]][1])),
  irLow=c(as.numeric(strsplit(strsplit(airCvdNotpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdUnder55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdAbove55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdFemalepVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdMalepVZV,split=",")[[1]][2],split="\\[")[[1]][2])),
  irUpp=c(as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdNotpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdUnder55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdAbove55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdFemalepVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdMalepVZV,split=",")[[1]][3]))),
  arFullCI=gsub(pattern="\\[ ",replacement="\\[",gsub(pattern=", 95% CI",replacement="",paste(sep="","AR ",c(
    ar2CvdNotpVZV,
    ar2CvdpVZV,
    ar2CvdUnder55pVZV,
    ar2CvdAbove55pVZV,
    ar2CvdFemalepVZV,
    ar2CvdMalepVZV
  ))))
) %>%
  dplyr::mutate(
    irFullCI=paste(sep="","IR ",format(nsmall=1,round(digits=1,ir))," [",format(nsmall=1,round(digits=1,irLow)),",",format(nsmall=1,round(digits=1,irUpp)),"]")
  )

gIrPlwh<-ggplot() +
  geom_bar(data=df,mapping=aes(x=idx,y=ir,fill=Grouping),stat="identity") +
  #geom_errorbar(data=df,mapping=aes(x=idx,y=ir,ymin=irLow,ymax=irUpp),width=0.1,alpha=0.75,lwd=0.4,col="darkgrey") +
  geom_text(data=df,mapping=aes(x=idx,y=ir+3.25,label=irFullCI),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(x=idx,y=ir,label=gsub(pattern=", ",replacement="",arFullCI)),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(label=pVZV,x=idx),y=-5,size=8) +
  geom_text(data=data.frame(lbl=c(rep("",2),"<55","55+","Female","Male"),x=1:6,col=df$Grouping),mapping=aes(label=lbl,x=x,col=col),y=-12,size=4) +
  geom_text(data=data.frame(lbl=factor(levels(df$Grouping),levels=levels(df$Grouping)),x=seq(1.5,5.5,by=2)),mapping=aes(label=lbl,x=x,col=lbl),y=-20,size=6) +
  geom_text(data=data.frame(lbl=c("-  no pVZV","+ pVZV"), x=c(1,1), y=c(105,110)), mapping=aes(x=x,y=y,label=lbl), size=5, hjust=0) +
  #geom_text(data=data.frame(x=4,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  scale_fill_manual(values=c("steelblue","orange","#2E8B57")) +
  scale_color_manual(values=c("steelblue","orange","#2E8B57")) +
  coord_cartesian(ylim=c(-18,110)) +
  ylim(-25,1000) +
  theme_minimal() +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(),panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16)) +
  guides(color=FALSE,fill=FALSE) +
  ylab("") +
  xlab("")

print(gIrPlwh + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)") )

pdf(width=8,height=8,file=paste(sep="_",outPrefix,"CIMT_CVDevents_FigureIncidenceRates_PLWH_barplot.pdf"))
print(gIrPlwh + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)") )
dev.off()
## quartz_off_screen 
##                 2
source("AbsRiskGraphs.R")

g_pVZV<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdpVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV",cptn=paste(sep="","10-year CVD risk ",ar10CvdpVZV,"."))
g_NopVZV<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdNotpVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="No pVZV",cptn=paste(sep="","10-year CVD risk ",ar10CvdNotpVZV,"."))

g_Above55<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdAbove55pVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV, age 55+ years",cptn=paste(sep="","10-year CVD risk ",ar10CvdAbove55pVZV,"."))
g_Under55<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdUnder55pVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="pVZV, age < 55 years",cptn=paste(sep="","10-year CVD risk ",ar10CvdUnder55pVZV,"."))

g_Male<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdMalepVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV, male",cptn=paste(sep="","10-year CVD risk  ",ar10CvdMalepVZV,"."))

g_Female<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdFemalepVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="pVZV, female",cptn=paste(sep="","10-year CVD risk  ",ar10CvdFemalepVZV,"."))

grid.arrange(top="PLWH",g_pVZV,g_NopVZV,g_Above55,g_Under55,g_Male,g_Female,ncol=2)

pdf(width=5,height=9,file=paste(sep="_",outPrefix,"CIMT_CVDevents_FigureIncidenceRates_PLWH.pdf"))
grid.arrange(top="PLWH",g_pVZV,g_NopVZV,g_Above55,g_Under55,g_Male,g_Female,ncol=2)
dev.off()

And now we repeat the graph for controls.

clinEventsTmp$category<-factor(clinEventsTmp$category)
clinEventsTmp$age_group_2lvls<-factor(clinEventsTmp$age_group_2lvls)

clinEventsTmpCtrl<-clinEventsTmp %>%
  dplyr::filter(ptype=="Control")

tt<-table(clinEventsTmpCtrl$category)
ttt<-data.frame(
  CVD.clinical=tt["CVD"],
  CVD.CIMT=tt["CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt

nEvents<-unlist(tt)
tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="Control"])/(1000*365.25))

tt<-nEvents/tObs
ttLow<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
ttUpp<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs

tt<-t(as.matrix(tt))
ttLow<-t(as.matrix(ttLow))
ttUpp<-t(as.matrix(ttUpp))

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
  }
}


tmp<-clinEventsTmpCtrl %>% dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")
tt<-table(tmp$age_group_2lvls,tmp$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  if(i==1){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age<55 & rhiccaDatWide$crf.PLWH=="Control" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  }else if(i==2){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.age>=55 & rhiccaDatWide$crf.PLWH=="Control" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="<55"){
        airCvdUnder55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdUnder55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="55+"){
        airCvdAbove55pVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdAbove55pVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}


tmp<-clinEventsTmpCtrl %>%
  dplyr::filter(!is.na(vzvStatus) & vzvStatus=="persistently high titres")

tt<-table(tmp$gender,tmp$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
    nEvents<-unlist(tt[i,])
    tObs<-sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.gender==rownames(ttCount)[i] & rhiccaDatWide$crf.PLWH=="Control" & !is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels=="persistently high titres"])/(1000*365.25))
    
    tt[i,]<-nEvents/tObs
    ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
    ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    
    if(j==3){
      if(rownames(ttCount)[i]=="Female"){
        airCvdFemalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdFemalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
      if(rownames(ttCount)[i]=="Male"){
        airCvdMalepVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
        ar10CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
        ar5CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
        ar2CvdMalepVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    }
  }
}

pidsWithVzv<-rhiccaDatWide$pid[!is.na(rhiccaDatWide$vzvStatus)]
clinEventsTmpCtrl2<-clinEventsTmpCtrl %>%
  dplyr::filter(pid %in% pidsWithVzv) %>%
  dplyr::mutate(vzvStatus_2levels=ifelse(vzvStatus=="persistently high titres","persistently high titres","not persistently high titres"))

tt<-table(clinEventsTmpCtrl2$vzvStatus_2levels,clinEventsTmpCtrl2$category)
ttt<-data.frame(
  CVD.clinical=tt[,"CVD"],
  CVD.CIMT=tt[,"CIMT"]
) %>%
  dplyr::mutate(
    CVD.clinicalAndCIMT=CVD.clinical+CVD.CIMT
  )
tt<-ttt

ttCount<-tt
ttLow<-tt
ttUpp<-tt
for(i in 1:nrow(ttCount)){
  nEvents<-unlist(tt[i,])
  tObs<-sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus_2levels) & rhiccaDatWide$vzvStatus_2levels==rownames(tt)[i] & rhiccaDatWide$crf.PLWH=="Control"])/(1000*365.25))
  
  tt[i,]<-nEvents/tObs
  ttLow[i,]<-(qchisq(p=0.025,df=2*nEvents)/2)/tObs
  ttUpp[i,]<-(qchisq(p=0.975,df=2*(nEvents+1))/2)/tObs
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"])")
    if(rownames(ttCount)[i]=="not persistently high titres"){
      airCvdNotpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdNotpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
    if(rownames(ttCount)[i]=="persistently high titres"){
      airCvdpVZV=paste(sep="",format(nsmall=3,round(digits=3,tt[i,j])),", 95% CI [",paste(collapse=", ",format(nsmall=3,round(digits=3,c(ttLow[i,j],ttUpp[i,j])))),"]")
      ar10CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=10*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=10*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=10*ttUpp[i,j]/1000)))))),"%]")
      ar5CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=5*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=5*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=5*ttUpp[i,j]/1000)))))),"%]")
      ar2CvdpVZV=paste(sep="",format(nsmall=2,round(digits=2,100*(1-ppois(q=0,lambda=2*tt[i,j]/1000)))),"%, 95% CI [",paste(collapse="%, ",format(nsmall=2,round(digits=2,c(100*(1-ppois(q=0,lambda=2*ttLow[i,j]/1000)),100*(1-ppois(q=0,lambda=2*ttUpp[i,j]/1000)))))),"%]")
      }
  }
}

totCases<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])
incNonExp<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus!="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
incExp<-sum(ttCountCount[rownames(ttCountCount)=="persistently high titres","CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
incOverall<-sum(ttCountCount[,"CVD.clinicalAndCIMT"])/sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
hypoCases<-sum(ttCountCount[rownames(ttCountCount)!="persistently high titres","CVD.clinicalAndCIMT"])+incNonExp*sum(as.numeric(rhiccaDatWide$obsTime[!is.na(rhiccaDatWide$vzvStatus) & rhiccaDatWide$vzvStatus=="persistently high titres" & rhiccaDatWide$crf.PLWH=="PLWH"])/(1000*365.25))
pafClinCimt<-(totCases-hypoCases)/totCases


modClinEventsConfirmedCVDwithCIMT.univariable.2levels<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Control"),glm(numClinEventsPerParticipantCVDwithCIMT~vzvStatus_2levels,family="quasipoisson",offset=log(obsTime/(1000*365.25)+1)))

cvdClinicalCimtPoisP.2levels<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$p.value[summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.2levels))$term=="vzvStatus_2levelspersistently high titres"]
df<-data.frame(
  idx=1:6,
  pVZV=c("-",rep("+",5)),
  Grouping=factor(c(rep("All Controls",2),rep("Age",2),rep("Sex",2)),levels=c("All Controls","Age","Sex")),
  Characteristic=c(rep("",2),"<55","55+","Female","Male"),
  ir=c(as.numeric(strsplit(airCvdNotpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdpVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdUnder55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdAbove55pVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdFemalepVZV,split=",")[[1]][1]),
       as.numeric(strsplit(airCvdMalepVZV,split=",")[[1]][1])),
  irLow=c(as.numeric(strsplit(strsplit(airCvdNotpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdpVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdUnder55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdAbove55pVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdFemalepVZV,split=",")[[1]][2],split="\\[")[[1]][2]),
          as.numeric(strsplit(strsplit(airCvdMalepVZV,split=",")[[1]][2],split="\\[")[[1]][2])),
  irUpp=c(as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdNotpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdpVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdUnder55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdAbove55pVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdFemalepVZV,split=",")[[1]][3])),
          as.numeric(gsub(pattern=" |\\]",replace="",strsplit(airCvdMalepVZV,split=",")[[1]][3]))),
  arFullCI=gsub(pattern="\\[ ",replacement="\\[",gsub(pattern=", 95% CI",replacement="",paste(sep="","AR ",c(
    ar2CvdNotpVZV,
    ar2CvdpVZV,
    ar2CvdUnder55pVZV,
    ar2CvdAbove55pVZV,
    ar2CvdFemalepVZV,
    ar2CvdMalepVZV
  ))))
) %>%
  dplyr::mutate(
    irFullCI=paste(sep="","IR ",format(nsmall=1,round(digits=1,ir))," [",format(nsmall=1,round(digits=1,irLow)),",",format(nsmall=1,round(digits=1,irUpp)),"]")
  )

gIrCtrl<-ggplot() +
  geom_bar(data=df,mapping=aes(x=idx,y=ir,fill=Grouping),stat="identity") +
  #geom_errorbar(data=df,mapping=aes(x=idx,y=ir,ymin=irLow,ymax=irUpp),width=0.1,col="darkgrey",lwd=0.4,alpha=0.75) +
  geom_text(data=df,mapping=aes(x=idx,y=ir+3.25,label=irFullCI),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(x=idx,y=ir,label=gsub(pattern=", ",replacement="",arFullCI)),size=2.6,hjust=0.5,nudge_y = 2) +
  geom_text(data=df,mapping=aes(label=pVZV,x=idx),y=-5,size=8) +
  geom_text(data=data.frame(lbl=c(rep("",2),"<55","55+","Female","Male"),x=1:6,col=df$Grouping),mapping=aes(label=lbl,x=x,col=col),y=-12,size=4) +
  geom_text(data=data.frame(lbl=factor(levels(df$Grouping),levels=levels(df$Grouping)),x=seq(1.5,5.5,by=2)),mapping=aes(label=lbl,x=x,col=lbl),y=-20,size=6) +
  geom_text(data=data.frame(lbl=c("-  no pVZV","+ pVZV"), x=c(1,1), y=c(105,110)), mapping=aes(x=x,y=y,label=lbl), size=5, hjust=0) +
  #geom_text(data=data.frame(x=2,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  #geom_text(data=data.frame(x=3,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  #geom_text(data=data.frame(x=4,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  #geom_text(data=data.frame(x=5,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  #geom_text(data=data.frame(x=6,y=130,lbl="//"),mapping=aes(x=x,y=y,label=lbl),col="darkgrey",size=5) +
  scale_fill_manual(values=c("steelblue","orange","#2E8B57")) +
  scale_color_manual(values=c("steelblue","orange","#2E8B57")) +
  coord_cartesian(ylim=c(-18,110)) +
  ylim(-25,1000) +
  theme_minimal() +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(),panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16)) +
  guides(color=FALSE,fill=FALSE) +
  ylab("") +
  xlab("")

print(gIrCtrl + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)"))

pdf(width=8,height=8,file=paste(sep="_",outPrefix,"CIMT_CVDevents_FigureIncidenceRates_Controls_barplot.pdf"))
print(gIrCtrl + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)"))
dev.off()
## quartz_off_screen 
##                 2
pdf(width=24,height=8,file=paste(sep="_",outPrefix,"SFig2_CIMT_CVDevents_FigureIncidenceRates_barplot.pdf"))
grid.arrange(
  gIrAll+labs(title="All participants") + theme(plot.title = element_text(hjust = 0.5)),
  gIrPlwh+labs(title="PLWH") + theme(plot.title = element_text(hjust = 0.5)),
  gIrCtrl+labs(title="HIV negative") + theme(plot.title = element_text(hjust = 0.5)),
  nrow=1)
dev.off()
## quartz_off_screen 
##                 2
pdf(width=8,height=8,file=paste(sep="_",outPrefix,"SFig2a_CIMT_CVDevents_FigureIncidenceRates_barplot_All.pdf"))
gIrAll+labs(title="All participants") + theme(plot.title = element_text(hjust = 0.5))
dev.off()
## quartz_off_screen 
##                 2
pdf(width=8,height=8,file=paste(sep="_",outPrefix,"SFig2b_CIMT_CVDevents_FigureIncidenceRates_barplot_PLWH.pdf"))
gIrPlwh+labs(title="PLWH") + theme(plot.title = element_text(hjust = 0.5)) + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)")
dev.off()
## quartz_off_screen 
##                 2
pdf(width=8,height=8,file=paste(sep="_",outPrefix,"SFig2c_CIMT_CVDevents_FigureIncidenceRates_barplot_Controls.pdf"))
gIrCtrl+labs(title="HIV negative") + theme(plot.title = element_text(hjust = 0.5)) + ylab("CBD/CVD sub-/clinical event rate (per 1,000 person-years)")
dev.off()
## quartz_off_screen 
##                 2
source("AbsRiskGraphs.R")

g_pVZV<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdpVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV",cptn=paste(sep="","10-year CVD risk ",ar10CvdpVZV,"."))
g_NopVZV<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdNotpVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="No pVZV",cptn=paste(sep="","10-year CVD risk ",ar10CvdNotpVZV,"."))

g_Above55<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdAbove55pVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV, age 55+ years",cptn=paste(sep="","10-year CVD risk ",ar10CvdAbove55pVZV,"."))
g_Under55<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdUnder55pVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="pVZV, age < 55 years",cptn=paste(sep="","10-year CVD risk ",ar10CvdUnder55pVZV,"."))

g_Male<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdMalepVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="orange",ttl="pVZV, male",cptn=paste(sep="","10-year CVD risk  ",ar10CvdMalepVZV,"."))
g_Female<-arPlot(ir=100*as.numeric(gsub(pattern="%",replacement="",strsplit(ar10CvdFemalepVZV,split=",")[[1]][1])),denom=10000,nrows=100,col="darkgreen",ttl="pVZV, female",cptn=paste(sep="","10-year CVD risk  ",ar10CvdFemalepVZV,"."))

grid.arrange(top="Controls",g_pVZV,g_NopVZV,g_Above55,g_Under55,g_Male,g_Female,ncol=2)

pdf(width=5,height=9,file=paste(sep="_",outPrefix,"CIMT_CVDevents_FigureIncidenceRates_Ctrl.pdf"))
grid.arrange(top="Controls",g_pVZV,g_NopVZV,g_Above55,g_Under55,g_Male,g_Female,ncol=2)
dev.off()

The absolute risk (expressed as an incidence rate) of clinical and sub-clinical CIMT events is 37.255, 95% CI [ 0.943, 207.573] per 1,000 person-years in controls with pVZV compared to 9.891, 95% CI [ 1.198, 35.730] per 1,000 person-years in those without pVZV (Poisson p-value for this difference p=0.250).

We can also express this in terms of 5-year and 10-year risk. For this we make use of the cumulative distribution function of the Poisson distribution, using the above reported incidence rates and their associated 95% CIs. The Poisson test p-value for the difference in risk remains of course the same, regardless how the risk is reported.

The absolute risk (expressed as the probability of 1 or more events within the next 10 years; in other words the 10-year risk) of clinical and sub-clinical CIMT events is 31.10%, 95% CI [ 0.94%, 87.45%] in controls with pVZV compared to 9.42%, 95% CI [ 1.19%, 30.04%] in those without pVZV.

In controls, the PAF for sub-clinical CIMT and clinical CVD events associated with pVZV is 0.182.

10.0.0.1 Extra figures for manuscript

PLWH - VZV, CMV and sub-/clinical events

gr<-expand.grid(c("No sub-/clinical CVD events","Sub-/clinical CVD events"),c("Enrolment","6months"),c("CMV","VZV"))

df<-data.frame(
  group=gr[,1],
  timepoint=gr[,2],
  marker=factor(gr[,3],levels=c("VZV","CMV")),
  n=NA,
  k=NA,
  prop=NA,
  propLow=NA,
  propUpp=NA
) %>%
  dplyr::mutate(
    timepointNum=case_when(timepoint=="Enrolment"~0,timepoint=="6months"~6),
    pValue=NA
  )

tmp<-clinEventsTmp #%>%
  #dplyr::filter(ptype=="PLWH")

pidsCvdEvent<-tmp$pid

tmp<-rhiccaDatWide %>%
  dplyr::filter(crf.ptype=="Patient") %>%
  dplyr::select(pid,vzv.vzv_enrolment,vzv.vzv_6months,cmv.cmv_enrolment,cmv.cmv_6months) %>%
  dplyr::mutate(
    group=factor(ifelse(pid %in% pidsCvdEvent,"Sub-/clinical CVD events","No sub-/clinical CVD events"))
  ) %>%
  tidyr::pivot_longer(cols=contains("_"),names_pattern="(vzv.vzv|cmv.cmv)_(.*)",names_to=c("marker","timepoint"),values_to="measurement") %>%
  dplyr::mutate(
    marker=factor(case_when(marker=="cmv.cmv"~"CMV",marker=="vzv.vzv"~"VZV"),levels=c("VZV","CMV")),
    timepoint=str_to_title(timepoint)
  )

for(i in 1:nrow(df)){
  df$n[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement))
  if(df$marker[i]=="VZV"){df$k[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement) & tmp$measurement>=vzvQuartiles["75%"])}
  if(df$marker[i]=="CMV"){df$k[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement) & tmp$measurement>=cmvQuartiles["75%"])}
  df$prop[i]<-df$k[i]/df$n[i]
  binomTmp<-binom.test(x=df$k[i],n=df$n[i])$conf.int
  df$propLow[i]<-binomTmp[1]
  df$propUpp[i]<-binomTmp[2]
  
  if(i %in% seq(2,nrow(df),by=2)){
    df$pValue[i-1]<-fisher.test(matrix(nrow=2,byrow=TRUE,c(df[i-1,"n"]-df[i-1,"k"],df[i-1,"k"],df[i,"n"]-df[i,"k"],df[i,"k"])))$p.value
  }
}

g1a<-df %>%
  dplyr::filter(marker=="VZV") %>%
  dplyr::mutate(
    timepointNum=case_when(group=="Sub-/clinical CVD events"~timepointNum-0.08,group=="No sub-/clinical CVD events"~timepointNum+0.08)
    ) %>%
  ggplot(mapping=aes(x=timepointNum,y=prop,ymin=propLow,ymax=propUpp,col=group,label=ifelse(pValue<0.05,"*","n.s."))) +
  geom_point(size=2) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_line(lwd=0.85) +
  geom_text(mapping=aes(x=timepointNum,y=ifelse(!is.na(pValue) & pValue<0.05,0.845,0.85),size=ifelse(!is.na(pValue) & pValue<0.05,14,12),fontface=ifelse(!is.na(pValue) & pValue<0.05,"bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  scale_color_manual(values=c("steelblue","orange"),name="") +
  scale_x_continuous(breaks=c(0,6),labels=c("Enrolment","6 months"),name="") +
  scale_size_continuous(limits = c(1,14)) +
  ylab("Proportion of IgG titres in top quartile") +
  guides(size=FALSE) +
  ylim(c(0,1)) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom",legend.direction="vertical")

g1b<-df %>%
  dplyr::filter(marker=="CMV") %>%
  dplyr::mutate(
    timepointNum=case_when(group=="Sub-/clinical CVD events"~timepointNum-0.08,group=="No sub-/clinical CVD events"~timepointNum+0.08)
    ) %>%
  ggplot(mapping=aes(x=timepointNum,y=prop,ymin=propLow,ymax=propUpp,col=group,label=ifelse(pValue<0.05,"*","n.s."))) +
  geom_point(size=2) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_line(lwd=0.85) +
  geom_text(mapping=aes(x=timepointNum,y=ifelse(!is.na(pValue) & pValue<0.05,0.845,0.85),size=ifelse(!is.na(pValue) & pValue<0.05,14,12),fontface=ifelse(!is.na(pValue) & pValue<0.05,"bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  scale_color_manual(values=c("steelblue","orange"),name="") +
  scale_x_continuous(breaks=c(0,6),labels=c("Enrolment","6 months"),name="") +
  scale_size_continuous(limits = c(1,14)) +
  ylab("") +
  guides(size=FALSE) +
  ylim(c(0,1)) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom",legend.direction="vertical")

dfRR<-data.frame(
  group=rep(c("not persistently high titres","persistently high titres"),2),
  RR=rep(c(1,NA),2),
  RRlogSE=NA,
  RRlow=NA,
  RRupp=NA,
  marker=factor(c(rep("VZV",2),rep("CMV",2)),levels=c("VZV","CMV")),
  sig=NA
)

# for(i in 1:nrow(dfRR)){
#   if(dfRR$marker[i]=="VZV"){
#     if(dfRR$group[i]!="persistently low titres"){
#       a0=sum(!is.na(clinEventsTmpPLWH$vzvStatus) & clinEventsTmpPLWH$vzvStatus=="persistently low titres")
#       a1=sum(!is.na(clinEventsTmpPLWH$vzvStatus) & clinEventsTmpPLWH$vzvStatus==dfRR$group[i])
#       t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$vzvStatus=="persistently low titres"],na.rm=TRUE))
#       t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$vzvStatus==dfRR$group[i]],na.rm=TRUE))
#       if((a0>0 | a1>0) & t0>0 & t1>0){
#         dfRR$RR[i]<-(a1/t1)/(a0/t0)
#         dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
#         if(a1>0){
#           dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
#           dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
#         }else{
#           tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
#           dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
#           dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
#         }
#         dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
#       }
#     }
#   }
#   if(dfRR$marker[i]=="CMV"){
#     if(dfRR$group[i]!="persistently low titres"){
#       a0=sum(!is.na(clinEventsTmpPLWH$cmvStatus) & clinEventsTmpPLWH$cmvStatus=="persistently low titres",dfRR$marker[i])
#       a1=sum(!is.na(clinEventsTmpPLWH$cmvStatus) & clinEventsTmpPLWH$cmvStatus==dfRR$group[i])
#       t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$cmvStatus=="persistently low titres"],na.rm=TRUE))
#       t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$cmvStatus==dfRR$group[i]],na.rm=TRUE))
#       if((a0>0 | a1>0) & t0>0 & t1>0){
#         dfRR$RR[i]<-(a1/t1)/(a0/t0)
#         dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
#         if(a1>0){
#           dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
#           dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
#         }else{
#           tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
#           dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
#           dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
#         }
#         dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
#       }
#     }
#   }
# }

for(i in 1:nrow(dfRR)){
  if(dfRR$marker[i]=="VZV"){
    if(dfRR$group[i]!="not persistently high titres"){
      a0=sum(clinEventsTmp$ptype=="PLWH" & !is.na(clinEventsTmp$vzvStatus_2levels) & clinEventsTmp$vzvStatus_2levels=="not persistently high titres")
      a1=sum(clinEventsTmp$ptype=="PLWH" & !is.na(clinEventsTmp$vzvStatus_2levels) & clinEventsTmp$vzvStatus_2levels==dfRR$group[i])
      t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH" & rhiccaDatWide$vzvStatus_2levels=="not persistently high titres"],na.rm=TRUE))
      t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH" & rhiccaDatWide$vzvStatus_2levels==dfRR$group[i]],na.rm=TRUE))
      if((a0>0 | a1>0) & t0>0 & t1>0){
        dfRR$RR[i]<-(a1/t1)/(a0/t0)
        dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
        if(a1>0){
          dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
          dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
        }else{
          tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
          dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
          dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
        }
        dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
      }
    }
  }
  if(dfRR$marker[i]=="CMV"){
    if(dfRR$group[i]!="not persistently high titres"){
      a0=sum(clinEventsTmp$ptype=="PLWH" & !is.na(clinEventsTmp$cmvStatus_2levels) & clinEventsTmp$cmvStatus_2levels=="not persistently high titres",dfRR$marker[i])
      a1=sum(clinEventsTmp$ptype=="PLWH" & !is.na(clinEventsTmp$cmvStatus_2levels) & clinEventsTmp$cmvStatus_2levels==dfRR$group[i])
      t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH" & rhiccaDatWide$cmvStatus_2levels=="not persistently high titres"],na.rm=TRUE))
      t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH=="PLWH" & rhiccaDatWide$cmvStatus_2levels==dfRR$group[i]],na.rm=TRUE))
      if((a0>0 | a1>0) & t0>0 & t1>0){
        dfRR$RR[i]<-(a1/t1)/(a0/t0)
        dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
        if(a1>0){
          dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
          dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
        }else{
          tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
          dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
          dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
        }
        dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
      }
    }
  }
}

g2a<-dfRR %>%
  dplyr::filter(marker=="VZV") %>%
  dplyr::mutate(
    group=factor(case_when(
      group=="not persistently high titres"~"Not persistently high titres\n(ref.)",
      group=="persistently high titres"~"Persistently high titres",
    ),levels=c("Not persistently high titres\n(ref.)","Persistently high titres")),
    RRupp=ifelse(is.nan(RRupp),500,dfRR$RRupp)
  ) %>%
  ggplot(mapping=aes(x=group,y=RR,ymin=RRlow,ymax=RRupp,label=sig)) +
  geom_point(size=3) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_hline(yintercept=1,lty=2,col="darkgrey") +
  geom_text(mapping=aes(y=ifelse(sig=="*",32,35),size=ifelse(sig=="*",14,12),fontface=ifelse(sig=="*","bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  #scale_color_manual(values=c("steelblue","orange"),name="") +
  #scale_x_continuous(breaks=c(0,6),labels=c("Enrolment","6 months"),name="") +
  ylab("Rate ratio for sub-/clinical events") +
  xlab("") +
  scale_size_continuous(limits = c(1,14)) +
  scale_y_continuous(trans="log10") +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom") +
  guides(size=FALSE) +
  coord_cartesian(ylim=c(0.045,50))

g2b<-dfRR %>%
  dplyr::filter(marker=="CMV") %>%
  dplyr::mutate(
    group=factor(case_when(
      group=="not persistently high titres"~"Not persistently high titres\n(ref.)",
      group=="persistently high titres"~"Persistently high titres",
    ),levels=c("Not persistently high titres\n(ref.)","Persistently high titres")),
    RRupp=ifelse(is.nan(RRupp),500,dfRR$RRupp)
  ) %>%
  ggplot(mapping=aes(x=group,y=RR,ymin=RRlow,ymax=RRupp,label=sig)) +
  geom_point(size=3) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_hline(yintercept=1,lty=2,col="darkgrey") +
  geom_text(mapping=aes(y=ifelse(sig=="*",32,35),size=ifelse(sig=="*",14,12),fontface=ifelse(sig=="*","bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  #scale_color_manual(values=c("steelblue","orange"),name="") +
  #scale_x_continuous(breaks=c(0,6),labels=c("Enrolment","6 months"),name="") +
  ylab("") +
  xlab("") +
  scale_size_continuous(limits = c(1,14)) +
  scale_y_continuous(trans="log10") +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom") +
  guides(size=FALSE) +
  coord_cartesian(ylim=c(0.045,50))

gPanelA<-(g1a | g1b) / (g2a | g2b) + plot_annotation(tag_levels=list(c("A","B","C","D")))

gTopA<-ggplot(mapping=aes(x=0.5,y=1,label="All participants")) + geom_text(size=16,fontface="bold") + theme_void()

pdf(width=7.5,height=12,file=paste(sep="_",outPrefix,"Fig2_HerpesGroups_HerpesTitres_RRofEvents_PLWH.pdf"))
(g1a | g1b) / (g2a | g2b) + plot_annotation(tag_levels=list(c("A","B","C","D")))
dev.off()
## quartz_off_screen 
##                 2

PLWH - CD4, VL and sub-/clinical events

gr<-expand.grid(c("No sub-/clinical CVD events","Sub-/clinical CVD events"),c("Enrolment","6months","12months"),c("CD4+ count","HIV VL"))

df<-data.frame(
  group=gr[,1],
  timepoint=gr[,2],
  marker=factor(gr[,3],levels=c("CD4+ count","HIV VL")),
  n=NA,
  k=NA,
  prop=NA,
  propLow=NA,
  propUpp=NA
) %>%
  dplyr::mutate(
    timepointNum=case_when(timepoint=="Enrolment"~0,timepoint=="6months"~6,timepoint=="12months"~12),
    pValue=NA
  )

tmp<-clinEventsTmp %>%
  dplyr::filter(ptype=="PLWH")

pidsCvdEvent<-tmp$pid

tmp<-rhiccaDatWide %>%
  dplyr::filter(crf.ptype=="Patient") %>%
  dplyr::select(pid,lims.CD4_Absolute_enrolment,lims.CD4_Absolute_6months,lims.CD4_Absolute_12months,lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment,lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months,lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months) %>%
  dplyr::mutate(
    group=factor(ifelse(pid %in% pidsCvdEvent,"Sub-/clinical CVD events","No sub-/clinical CVD events"))
  ) %>%
  tidyr::pivot_longer(cols=contains("_"),names_pattern="(lims.CD4_Absolute|lims.HIV_Abbott_Viral_Load_0pt2ml_P)_(.*)",names_to=c("marker","timepoint"),values_to="measurement") %>%
  dplyr::mutate(
    marker=factor(case_when(marker=="lims.CD4_Absolute"~"CD4+ count",marker=="lims.HIV_Abbott_Viral_Load_0pt2ml_P"~"HIV VL"),levels=c("CD4+ count","HIV VL")),
    timepoint=str_to_title(timepoint)
  )

for(i in 1:nrow(df)){
  df$n[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement))
  if(df$marker[i]=="CD4+ count"){df$k[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement) & tmp$measurement<200)}
  if(df$marker[i]=="HIV VL"){df$k[i]<-sum(tmp$marker==df$marker[i] & tmp$group==df$group[i] & tmp$timepoint==df$timepoint[i] & !is.na(tmp$measurement) & tmp$measurement>1000)}
  df$prop[i]<-df$k[i]/df$n[i]
  binomTmp<-binom.test(x=df$k[i],n=df$n[i])$conf.int
  df$propLow[i]<-binomTmp[1]
  df$propUpp[i]<-binomTmp[2]
  
  if(i %in% seq(2,nrow(df),by=2)){
    df$pValue[i-1]<-fisher.test(matrix(nrow=2,byrow=TRUE,c(df[i-1,"n"]-df[i-1,"k"],df[i-1,"k"],df[i,"n"]-df[i,"k"],df[i,"k"])))$p.value
  }
}

g3a<-df %>%
  dplyr::filter(marker=="CD4+ count") %>%
  dplyr::mutate(
    timepointNum=case_when(group=="Sub-/clinical CVD events"~timepointNum-0.08,group=="No sub-/clinical CVD events"~timepointNum+0.08),
    marker=case_when(marker=="CD4+ count"~"CD4+ count < 200",marker=="HIV VL"~"HIV VL > 1000")
    ) %>%
  ggplot(mapping=aes(x=timepointNum,y=prop,ymin=propLow,ymax=propUpp,col=group,label=ifelse(pValue<0.05,"*","n.s."))) +
  geom_point(size=2) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_line(lwd=0.85) +
  geom_text(mapping=aes(x=timepointNum,y=ifelse(!is.na(pValue) & pValue<0.05,0.975,1.00),size=ifelse(!is.na(pValue) & pValue<0.05,14,12),fontface=ifelse(!is.na(pValue) & pValue<0.05,"bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  scale_color_manual(values=c("steelblue","orange"),name="") +
  scale_x_continuous(breaks=c(0,6,12),labels=c("Enrolment","6 months","12 months"),name="") +
  scale_size_continuous(limits = c(1,14)) +
  ylab("Proportion of PLWH with uncontrolled HIV") +
  guides(size=FALSE) +
  ylim(c(0,1)) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom",legend.direction="vertical")

g3b<-df %>%
  dplyr::filter(marker=="HIV VL") %>%
  dplyr::mutate(
    timepointNum=case_when(group=="Sub-/clinical CVD events"~timepointNum-0.08,group=="No sub-/clinical CVD events"~timepointNum+0.08),
    marker=case_when(marker=="CD4+ count"~"CD4+ count < 200",marker=="HIV VL"~"HIV VL > 1000")
    ) %>%
  ggplot(mapping=aes(x=timepointNum,y=prop,ymin=propLow,ymax=propUpp,col=group,label=ifelse(pValue<0.05,"*","n.s."))) +
  geom_point(size=2) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_line(lwd=0.85) +
  geom_text(mapping=aes(x=timepointNum,y=ifelse(!is.na(pValue) & pValue<0.05,0.975,1.00),size=ifelse(!is.na(pValue) & pValue<0.05,14,12),fontface=ifelse(!is.na(pValue) & pValue<0.05,"bold","plain")),col="black") +
  theme_minimal() +
  facet_wrap(~marker,nrow=1) +
  scale_color_manual(values=c("steelblue","orange"),name="") +
  scale_x_continuous(breaks=c(0,6,12),labels=c("Enrolment","6 months","12 months"),name="") +
  scale_size_continuous(limits = c(1,14)) +
  ylab("") +
  guides(size=FALSE) +
  ylim(c(0,1)) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom",legend.direction="vertical")

# dfRR<-data.frame(
#   group=c("500+","350-499","200-349","<200","<150","150-999","1000+"),
#   RR=c(1,NA,NA,NA,1,NA,NA),
#   RRlogSE=NA,
#   RRlow=NA,
#   RRupp=NA,
#   marker=factor(c(rep("CD4+ count",4),rep("HIV VL",3)),levels=c("CD4+ count","HIV VL")),
#   sig=NA
# )

dfRR<-data.frame(
  group=c("Full immune restoration","Partial immune restoration","Minimal immune restoration","Complete virological suppression","Virological resurgence","Incomplete virological suppression"),
  RR=c(1,NA,NA,1,NA,NA),
  RRlogSE=NA,
  RRlow=NA,
  RRupp=NA,
  marker=factor(c(rep("CD4+ count",3),rep("HIV VL",3)),levels=c("CD4+ count","HIV VL")),
  sig=NA
)


clinEventsTmpPLWH<-clinEventsTmpPLWH %>%
  dplyr::mutate(
    cd4=rhiccaDatWide$lims.CD4_Absolute_enrolment[match(pid,rhiccaDatWide$pid)],
    vl=rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment[match(pid,rhiccaDatWide$pid)],
    cd4Restoration=rhiccaDatWide$cd4Restoration[match(pid,rhiccaDatWide$pid)],
    vlSuppression=rhiccaDatWide$vlSuppression[match(pid,rhiccaDatWide$pid)]
  ) %>%
  dplyr::mutate(
    cd4_grp=case_when(
      cd4>=500~"500+",
      cd4>=350 & cd4<500~"350-499",
      cd4>=200 & cd4<350~"200-349",
      cd4<200~"<200"
    ),
    vl_grp=case_when(
      vl<150~"<150",
      vl>=150 & vl<1000~"150-999",
      vl>=1000~"1000+"
    )
  )

rhiccaDatWide<-rhiccaDatWide %>%
    dplyr::mutate(
    cd4_grp_enrolment=case_when(
      lims.CD4_Absolute_enrolment>=500~"500+",
      lims.CD4_Absolute_enrolment>=350 & lims.CD4_Absolute_enrolment<500~"350-499",
      lims.CD4_Absolute_enrolment>=200 & lims.CD4_Absolute_enrolment<350~"200-349",
      lims.CD4_Absolute_enrolment<200~"<200"
    ),
    vl_grp_enrolment=case_when(
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment<150~"<150",
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment>=150 & lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment<1000~"150-999",
      lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment>=1000~"1000+"
    )
  )

for(i in 1:nrow(dfRR)){
  if(dfRR$marker[i]=="CD4+ count"){
    if(dfRR$group[i]!="Full immune restoration"){
      a0=sum(!is.na(clinEventsTmpPLWH$cd4Restoration) & clinEventsTmpPLWH$cd4Restoration=="Full immune restoration")
      a1=sum(!is.na(clinEventsTmpPLWH$cd4Restoration) & clinEventsTmpPLWH$cd4Restoration==dfRR$group[i])
      t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$cd4Restoration=="Full immune restoration"],na.rm=TRUE))
      t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$cd4Restoration==dfRR$group[i]],na.rm=TRUE))
      if((a0>0 | a1>0) & t0>0 & t1>0){
        dfRR$RR[i]<-(a1/t1)/(a0/t0)
        dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
        if(a1>0){
          dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
          dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
        }else{
          tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
          dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
          dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
        }
        dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
      }
    }
  }
  if(dfRR$marker[i]=="HIV VL"){
    if(dfRR$group[i]!="Complete virological suppression"){
      a0=sum(!is.na(clinEventsTmpPLWH$vlSuppression) & clinEventsTmpPLWH$vlSuppression=="Complete virological suppression",dfRR$marker[i])
      a1=sum(!is.na(clinEventsTmpPLWH$vlSuppression) & clinEventsTmpPLWH$vlSuppression==dfRR$group[i])
      t0=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$vlSuppression=="Complete virological suppression"],na.rm=TRUE))
      t1=as.numeric(sum(rhiccaDatWide$obsTime[rhiccaDatWide$crf.ptype=="Patient" & rhiccaDatWide$vlSuppression==dfRR$group[i]],na.rm=TRUE))
      if((a0>0 | a1>0) & t0>0 & t1>0){
        dfRR$RR[i]<-(a1/t1)/(a0/t0)
        dfRR$RRlogSE[i]<-sqrt(1/a0+1/a1)
        if(a1>0){
          dfRR$RRlow[i]<-exp(log(dfRR$RR[i])-qnorm(0.975)*dfRR$RRlogSE[i])
          dfRR$RRupp[i]<-exp(log(dfRR$RR[i])+qnorm(0.975)*dfRR$RRlogSE[i])
        }else{
          tmp<-rateratio.midp(x=c(a0,a1),y=c(t0,t1))
          dfRR$RRlow[i]<-tmp$measure["Exposed2","lower"]
          dfRR$RRupp[i]<-tmp$measure["Exposed2","upper"]
        }
        dfRR$sig[i]<-ifelse(dfRR$RRlow[i]<=1 & 1<=dfRR$RRupp[i],"n.s.","*")
      }
    }
  }
}

g4a<-dfRR %>%
  dplyr::filter(marker=="CD4+ count") %>%
  dplyr::mutate(
    group=factor(case_when(
      group=="Full immune restoration"~"Full immune restoration (ref.)",
      TRUE~group
    ),levels=c("Full immune restoration (ref.)","Partial immune restoration","Minimal immune restoration"))
  ) %>%
  ggplot(mapping=aes(x=group,y=RR,ymin=RRlow,ymax=RRupp,label=sig)) +
  geom_point(size=3) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_hline(yintercept=1,lty=2,col="darkgrey") +
  geom_text(mapping=aes(y=ifelse(sig=="*",32,35),size=ifelse(sig=="*",14,12),fontface=ifelse(sig=="*","bold","plain")),col="black") +
  theme_minimal() +
  ylab("Rate ratio for sub-/clinical events") +
  xlab("") +
  scale_size_continuous(limits = c(1,14)) +
  scale_y_continuous(trans="log10") +
  facet_wrap(~marker) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom") +
  guides(size=FALSE) +
  coord_cartesian(ylim=c(0.045,50))
  #labs(title="CD4+ count")

g4b<-dfRR %>%
  dplyr::filter(marker=="HIV VL") %>%
  dplyr::mutate(
    group=factor(case_when(
      group=="Complete virological suppression"~"Complete virological\nsuppression (ref.)",
      TRUE~group
    ),levels=c("Complete virological\nsuppression (ref.)","Virological resurgence","Incomplete virological suppression"))
  ) %>%
  ggplot(mapping=aes(x=group,y=RR,ymin=RRlow,ymax=RRupp,label=sig)) +
  geom_point(size=3) +
  geom_errorbar(width=0.2,alpha=0.65) +
  geom_hline(yintercept=1,lty=2,col="darkgrey") +
  geom_text(mapping=aes(y=ifelse(sig=="*",32,35),size=ifelse(sig=="*",14,12),fontface=ifelse(sig=="*","bold","plain")),col="black") +
  theme_minimal() +
  ylab("") +
  xlab("") +
  scale_size_continuous(limits = c(1,14)) +
  scale_y_continuous(trans="log10") +
  facet_wrap(~marker) +
  theme(axis.text.x = element_text(angle=45,hjust=1,vjust=1), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),text=element_text(size=16),legend.position = "bottom") +
  guides(size=FALSE) +
  coord_cartesian(ylim=c(0.045,50))
  #labs(title="HIV VL")

# g2<-grid.arrange(g2a,g2b,nrow=1)
# 
gPanelB<-(g3a | g3b) / (g4a | g4b) + plot_annotation(tag_levels=list(c("E","F","G","H")))

gTopB<-ggplot(mapping=aes(x=0.5,y=1,label="PLWH")) + geom_text(size=16,face="bold") + theme_void()

pdf(width=7.5,height=12,file=paste(sep="_",outPrefix,"Fig2_HIVcontrolGroups_CD4_VL_RRofEvents_PLWH.pdf"))
(g3a | g3b) / (g4a | g4b) + plot_annotation(tag_levels=list(c("E","F","G","H")))
dev.off()
## quartz_off_screen 
##                 2
g1a<-g1a + theme(text=element_text(size=20))
g1b<-g1b + theme(text=element_text(size=20))
g2a<-g2a + theme(text=element_text(size=20))
g2b<-g2b + theme(text=element_text(size=20))
g3a<-g3a + theme(text=element_text(size=20))
g3b<-g3b + theme(text=element_text(size=20))
g4a<-g4a + theme(text=element_text(size=20))
g4b<-g4b + theme(text=element_text(size=20))


pdf(width=18,height=18,file=paste(sep="_",outPrefix,"Fig2_RRofEvents_PLWH.pdf"))
#grid.arrange(gPanelA,gPanelB,nrow=1)
#(gTopA | gTopB) / (g1a | g1b | g3a | g3b) / (g2a | g2b | g4a | g4b) + plot_layout(heights=c(0.1,0.45,0.45)) +
# plot_annotation(tag_levels=list(c("","","A","B","E","F","C","D","G","H")))
(g1a | g1b | g3a | g3b) / (g2a | g2b | g4a | g4b) + plot_layout(heights=c(0.5,0.5)) +
plot_annotation(tag_levels=list(c("A","B","E","F","C","D","G","H")))
dev.off()
## quartz_off_screen 
##                 2

10.0.0.2 Viral control

clinEventsTmpPLWH <- clinEventsTmpPLWH %>%
  dplyr::mutate(
    vlBaseline=rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment[match(pid,rhiccaDatWide$pid)],
    vl6mts=rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months[match(pid,rhiccaDatWide$pid)],
    vl12mts=rhiccaDatWide$lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months[match(pid,rhiccaDatWide$pid)],
  )

clinEventsTmpPLWH %>%
  kable() %>%
  kable_styling(full_width = FALSE)
pid ptype artnaive artRegimen gender age_group cmvStatus vzvStatus cmvStatus_2levels vzvStatus_2levels eGFR_existingCKD category age_group_2lvls cd4 vl cd4Restoration vlSuppression cd4_grp vl_grp vlBaseline vl6mts vl12mts
RE11077 PLWH ART naive ART: No change to dolutegravir Male [45,55) no CVD <55 174 2318 <200 1000+ 2318
RE1111F PLWH prior ART ART: No change to dolutegravir Male [55,65) yes CVD 55+ 63 56740 <200 1000+ 56740
RE12045 PLWH ART naive ART: No change to dolutegravir Male [55,65) no CVD 55+ 107 637935 <200 1000+ 637935
RE1351K PLWH ART naive ART: No change to dolutegravir Male [35,45) no CVD <55 116 264938 <200 1000+ 264938
RE1394Z PLWH ART naive ART: No change to dolutegravir Female [35,45) no CVD <55 98 2141148 <200 1000+ 2141148
RE1504I PLWH prior ART ART: Change to dolutegravir Male [45,55) no CVD <55 288 36875 Full immune restoration Complete virological suppression 200-349 1000+ 36875 1 1
RE1571X PLWH prior ART ART: Change to dolutegravir Female [55,65) persistently low titres persistently low titres not persistently high titres not persistently high titres no CVD 55+ 149 20161 Partial immune restoration <200 1000+ 20161 1
RE16306 PLWH ART naive ART: No change to dolutegravir Male [45,55) no CVD <55 27 418846 <200 1000+ 418846
RE10445 PLWH ART naive ART: Change to dolutegravir Female [55,65) persistently low titres persistently low titres not persistently high titres not persistently high titres no CIMT 55+ 261 117923 Partial immune restoration Complete virological suppression 200-349 1000+ 117923 1 1
RE10453 PLWH ART naive ART: Change to dolutegravir Male [45,55) persistently high titres persistently high titres persistently high titres persistently high titres no CIMT <55 50 66601 Minimal immune restoration Complete virological suppression <200 1000+ 66601 150 1
RE1080Y PLWH prior ART ART: No change to dolutegravir Male [55,65) persistently low titres persistently high titres not persistently high titres persistently high titres no CIMT 55+ 280 426 Partial immune restoration Complete virological suppression 200-349 150-999 426 1 1
RE1096I PLWH prior ART ART: No change to dolutegravir Female [55,65) progression to high titres progression to low titres not persistently high titres not persistently high titres no CIMT 55+ 84 24083 Minimal immune restoration Complete virological suppression <200 1000+ 24083 1 150
RE1100L PLWH ART naive ART: Change to dolutegravir Male [55,65) no CIMT 55+ 75 27112 Minimal immune restoration Complete virological suppression <200 1000+ 27112 1 1
RE1137W PLWH prior ART ART: Change to dolutegravir Male [35,45) persistently low titres persistently high titres not persistently high titres persistently high titres no CIMT <55 223 8446 Partial immune restoration Complete virological suppression 200-349 1000+ 8446 1 150
RE1486R PLWH ART naive ART: No change to dolutegravir Female [65,Inf) progression to high titres persistently low titres not persistently high titres not persistently high titres no CIMT 55+ 173 9114 Minimal immune restoration Complete virological suppression <200 1000+ 9114 1 1
RE1860F PLWH prior ART ART: Change to dolutegravir Female [55,65) persistently low titres persistently high titres not persistently high titres persistently high titres no CIMT 55+ 630 10077 Full immune restoration Complete virological suppression 500+ 1000+ 10077 1 1
RE19439 PLWH prior ART ART: No change to dolutegravir Female [45,55) persistently low titres persistently high titres not persistently high titres persistently high titres no CIMT <55 99 22927 Minimal immune restoration Complete virological suppression <200 1000+ 22927 1 1
RE1008D PLWH prior ART ART: No change to dolutegravir Female [35,45) persistently high titres progression to low titres persistently high titres not persistently high titres no PWV <55 140 3306 Partial immune restoration Complete virological suppression <200 1000+ 3306 1 150
RE10453 PLWH ART naive ART: Change to dolutegravir Male [45,55) persistently high titres persistently high titres persistently high titres persistently high titres no PWV <55 50 66601 Minimal immune restoration Complete virological suppression <200 1000+ 66601 150 1
RE11245 PLWH prior ART ART: Change to dolutegravir Male [45,55) persistently low titres persistently low titres not persistently high titres not persistently high titres no PWV <55 561 2778 Partial immune restoration Complete virological suppression 500+ 1000+ 2778 1 150
RE12053 PLWH ART naive ART: No change to dolutegravir Male [35,45) no PWV <55 330 75204 Full immune restoration Complete virological suppression 200-349 1000+ 75204 1 1
RE1251S PLWH ART naive ART: Change to dolutegravir Male [55,65) no PWV 55+ 306 225959 Partial immune restoration Complete virological suppression 200-349 1000+ 225959 1 1
RE13738 PLWH ART naive ART: Change to dolutegravir Female [45,55) persistently low titres persistently low titres not persistently high titres not persistently high titres no PWV <55 188 442092 Partial immune restoration Complete virological suppression <200 1000+ 442092 1 1
RE13834 PLWH ART naive ART: No change to dolutegravir Male [35,45) persistently high titres persistently high titres persistently high titres persistently high titres no PWV <55 62 611993 Minimal immune restoration <200 1000+ 611993 150
RE1424I PLWH ART naive ART: Change to dolutegravir Male [35,45) persistently low titres progression to high titres not persistently high titres not persistently high titres no PWV <55 132 261297 Partial immune restoration Complete virological suppression <200 1000+ 261297 1 1
RE1459X PLWH ART naive ART: Change to dolutegravir Male [55,65) persistently low titres persistently low titres not persistently high titres not persistently high titres no PWV 55+ 9178 Full immune restoration Complete virological suppression 1000+ 9178 1 1
RE1557T PLWH ART naive ART: Change to dolutegravir Female [45,55) persistently low titres persistently low titres not persistently high titres not persistently high titres no PWV <55 620 3257 Partial immune restoration 500+ 1000+ 3257 198
RE19551 PLWH prior ART ART: Change to dolutegravir Male [35,45) no PWV <55 Partial immune restoration Complete virological suppression 1 1

10.0.1 Hypothetical vaccine trial

Given the above results, we can consider how large a vaccine efficacy trial we would need to run to demonstrate an effect of a VZV vaccine on CVD outcome (clinical and sub-clinical CIMT events).

The design for such an hypothetical trial would be a standard 2 parellel arms design. There are considerable degrees of freedom around lengths of study and what population to recruit. Below we list our assumptions - subject to modification. Please not the distinction between study arm (VZV vaccine or control) and zoster infection group (pVZV or not).

  • Study design: 2-arm, randomised controlled trial.

  • Study duration: 30 months (for pragmatic reasons: 6 months between vaccination and first zoster measurement, then 24 months of follow-up for CVD outcome).

  • Intervention: varicella zoster vaccine (most likely the recombinant vaccine as evaluated in https://doi.org/10.1093/cid/ciac549).

  • Endpoint: count outcome of the number of CVD events (clinical or sub-clinical CIMT as defined in earlier sections).

  • Assumptions (based on data from RHICCA):

    • Prevalence of pVZV in control arm: 17.9% (in RHICCA 74 out of 413 PLWH with recorded VZV status has pVZV).
    • Target vaccine efficacy range: 10% to 60%.
    • Event rates in pVZV group: 31.160 per 1,000 person-years.
    • Event rates in pVZV group: 5,653 per 1,000 person-years.
    • Loss-to-follow-up over 30 months: 25% (this was 26.7% in RHICCA over 24 months; but we expect slightly less LTFU in a trial setting).
  • Analysis will consist of a simple Poisson test comparing the rate of events between study arms.

  • We will aim for 80% power at a 5% significance level.

With the above assumptions regarding pVZV prevalence and event rates in the pVZV and non-pVZV groups, this corresponds to an event rate of 10.219 events per 1,000 person-years in the vaccine arm and between 7.479 (60% efficacy) and 9.762 (10% efficacy) events per 1,000 person-years in the control group.

The design would need to recruit PLWH, initiated on ART at recruitment, age range 35-55 years of age, healthy except for HIV status. Participants would be recruited, consented, then randomised to zoster vaccine or control with the vaccine administered at the recruitment visit or shortly thereafter. VZV would be measured first 6 months after vaccination and then again 30 months after vaccination. The primary analysis would consider an intention-to-treat population with the full 2.5 years since vaccination counting towards to primary outcome of CVD events. A secondary analysis would consider the same population but only the final 2 years of follow-up.

Based on these assumptions, we get the sample sizes listed in 10.3 and shown on 10.1.

library(PASSED)

ssDf<-data.frame(
  VE=seq(0.1,0.6,by=0.1),
  prevalence=0.179,
  LTFU=0.25,
  followUpTime="2 years",
  rateCtrl=NA,
  rateVacc=NA,
  nPerGroup=NA,
  nPerGroupLTFU=NA,
  nTotal=NA
) %>%
  dplyr::mutate(
    rateCtrl=prevalence*31.16/1000+(1-prevalence)*5.653/1000,
    rateVacc=(1-VE)*prevalence*31.16/1000+(1-(1-VE)*prevalence)*5.653/1000,
  )

for(i in 1:nrow(ssDf)){
  ssDf$nPerGroup[i]<-ceiling(power_Poisson(power=0.8,equal.sample=TRUE,sig.level=0.05,lambda1=ssDf$rateCtrl[i],lambda2=ssDf$rateVacc[i],t1=2,t2=2,RR0=1,alternative="two.sided")$N)
}

ssDf<-ssDf %>%
  dplyr::mutate(
    nPerGroupLTFU=ceiling(nPerGroup/(1-LTFU)),
    nTotal=2*ceiling(nPerGroup/(1-LTFU))
  )

ssDf %>%
  kable(caption="Sample size for a hypothetical varicella zoster vaccine trial.",row.names=F,col.names=c("Vaccine efficacy","Prevalence of pVZV","LTFU","Follow-up time","Event rate in control arm (per person-year)","Event rate in vaccine arm (per person-year)","Sample size (per group, no LTFU)","Sample size (per group, with LTFU)","Sample size (total trial)")) %>%
  kable_styling(full_width=FALSE)
Table 10.3: Sample size for a hypothetical varicella zoster vaccine trial.
Vaccine efficacy Prevalence of pVZV LTFU Follow-up time Event rate in control arm (per person-year) Event rate in vaccine arm (per person-year) Sample size (per group, no LTFU) Sample size (per group, with LTFU) Sample size (total trial)
0.1 0.179 0.25 2 years 0.0102188 0.0097622 373555 498074 996148
0.2 0.179 0.25 2 years 0.0102188 0.0093056 90580 120774 241548
0.3 0.179 0.25 2 years 0.0102188 0.0088490 39004 52006 104012
0.4 0.179 0.25 2 years 0.0102188 0.0083925 21231 28308 56616
0.5 0.179 0.25 2 years 0.0102188 0.0079359 13133 17511 35022
0.6 0.179 0.25 2 years 0.0102188 0.0074793 8802 11736 23472
ssDf %>%
  ggplot(mapping=aes(x=VE,y=nTotal)) +
  geom_point(col="orange",size=2) +
  geom_line(col="orange",lwd=1) +
  theme_minimal() +
  xlab("Vaccine efficacy") +
  ylab("Total sample size") +
  labs(caption="pVZV prevalence in control arm = 17.9%.\nCVD event rate in pVZV group = 31.160/1,000 PY, CVD event rate in non-pVZV group = 5.653/1000 PY.\nLTFU = 25%.\nFollow-up period = 24 months.") +
  scale_y_continuous(trans="log10")
Sample size for a hypothetical vaccine trial as a function of vaccine efficacy.

Figure 10.1: Sample size for a hypothetical vaccine trial as a function of vaccine efficacy.

# modClinEvents<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPerParticipant~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment,family="quasipoisson"))
# 
# modClinEventsNoOnset<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPerParticipantNoOnset~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange,family="quasipoisson"))
# 
# modClinEventsNoPwvCimtAbpi<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPerParticipantNoPwvCimtAbpi~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange+cmvStatus+vzvStatus,family="quasipoisson"))
# 
# modClinEventsConfirmed<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipant~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange,family="quasipoisson"))
# 
# modClinEventsConfirmedWithDerivedWithoutPwvCimtAbpi<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantWithDerivedWithoutPwvCimtAbpi~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange,family="quasipoisson"))
# 
# modClinEventsPwvCimtAbpi<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPwvCimtAbpi~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmv.cmv_6months+vzv.vzv_6months,family="quasipoisson"))
# 
# modClinEventsPwvCimt<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPwvCimt~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus,family="quasipoisson"))
# 
# modClinEventsCVD<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPerParticipantCVD~crf.ptype+crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+lum.CD163_enrolment+lum.ICAM1_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange,family="quasipoisson"))
# 
# modClinEventsConfirmedCVD<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~crf.ptype*crf.gender+crf.age+physio.waisthip_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus+vzvStatus,family="quasipoisson"))
# 
# modClinEventsConfirmedCVD.simple<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~crf.ptype+crf.gender+crf.age,family="quasipoisson"))
# 
# modClinEventsConfirmedCVD.univariable<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~crf.ptype,family="quasipoisson"))
# 
# modClinEventsConfirmedCVD.univariable.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~crf.ptype+cmvStatus+vzvStatus,family="quasipoisson"))
# 
# modClinEventsConfirmedCVD.simple.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVD~crf.ptype+crf.gender+crf.age+cmvStatus+vzvStatus,family="quasipoisson"))

modClinEventsConfirmedCVDwithCIMT.simple<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~crf.ptype+crf.gender+crf.age,offset=obsTime/(1000*365.25),family="quasipoisson"))

modClinEventsConfirmedCVDwithCIMT.univariable.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~crf.ptype+cmvStatus_2levels+vzvStatus_2levels,offset=obsTime/(1000*365.25),family="quasipoisson"))

modClinEventsConfirmedCVDwithCIMT.simple.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~crf.ptype+crf.gender+crf.age+cmvStatus_2levels+vzvStatus_2levels,offset=obsTime/(1000*365.25),family="quasipoisson"))

modClinEventsConfirmedCVDwithCIMT.full<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels,offset=obsTime/(1000*365.25),family="quasipoisson"))

modClinEventsConfirmedCVDwithCIMT.simple<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMT~crf.ptype+crf.gender+crf.age,offset=obsTime/(1000*365.25),family="quasipoisson"))

# modClinEventsConfirmedCVDwithCIMTPWV.simple<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMTPWV~crf.ptype+crf.gender+crf.age,family="quasipoisson"))
# 
# modClinEventsConfirmedCVDwithCIMTPWV.univariable.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMTPWV~crf.ptype+cmvStatus+vzvStatus,family="quasipoisson"))
# 
# modClinEventsConfirmedCVDwithCIMTPWV.simple.CmzVzv<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantCVDwithCIMTPWV~crf.ptype+crf.gender+crf.age+cmvStatus+vzvStatus,family="quasipoisson"))


modClinEventsSystemic<-with(rhiccaDatWide_impMice.clinEvents,glm(numClinEventsPerParticipantSystemic~crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lum.CD163_enrolment+lum.ICAM1_enrolment+pwv.pwv_enrolment+pwvChange+cimt.cimt_enrolment+cimtChange,family="quasipoisson"))

modClinEventsConfirmedSystemic<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantSystemic~crf.ptype*crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels,family="quasipoisson"))
tab1<-summary(pool(modClinEventsConfirmedCVDwithCIMT.simple)) %>%
  as.data.frame() %>%
  dplyr::select(!term) %>%
  mutate(rownum=1:nrow(summary(pool(modClinEventsConfirmedCVDwithCIMT.simple)))) %>%
  mutate(estimate=exp(estimate)) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum))

tab2<-summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.CmzVzv)) %>%
  as.data.frame() %>%
  dplyr::select(!term) %>%
  mutate(rownum=1:nrow(summary(pool(modClinEventsConfirmedCVDwithCIMT.univariable.CmzVzv)))) %>%
  mutate(estimate=exp(estimate)) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum))

tab3<-summary(pool(modClinEventsConfirmedCVDwithCIMT.simple.CmzVzv)) %>%
  as.data.frame() %>%
  dplyr::select(!term) %>%
  mutate(rownum=1:nrow(summary(pool(modClinEventsConfirmedCVDwithCIMT.simple.CmzVzv)))) %>%
  mutate(estimate=exp(estimate)) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum))

tab4<-summary(pool(modClinEventsConfirmedCVDwithCIMT.full)) %>%
  as.data.frame() %>%
  dplyr::select(!term) %>%
  mutate(rownum=1:nrow(summary(pool(modClinEventsConfirmedCVDwithCIMT.full)))) %>%
  mutate(estimate=exp(estimate)) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum))

tabAllMods<-rbind(tab1,tab2,tab3,tab4)

rnames<-c(
  c("Intercept","Participant type PLWH","Sex male","Age (in years)"),
  c("Intercept ","Participant type PLWH ","CMV: persistently high titres","VZV: persistently high titres"),
  c("Intercept  ","Participant type PLWH  ","Sex male ","Age (in years) ","CMV: persistently high titres ","VZV: persistently high titres "),
  c("Intercept   ","Participant type PLWH   ","Sex male  ","Age (in years)  ","BMI","Diastolic blood pressure (enrolment)","Systolic blood pressure (enrolment)","Glucose (enrolment)","Cholesterol (enrolment)","CMV: persistently high titres  ","VZV: persistently high titres  ")
)

tabAllMods %>%
  kableRn(caption="Results for unadjusted, minimally adjusted and fully adjusted Poisson regression models for the number of confirmed CVD clinical events and sub-clinical CIMT derived events per 1,000 person-years. Models fitted to multiply imputed data. The estimate column below shows the reference risk for the intercept row and relative risks associated with each variable.",digits=4,row_names=rnames,escape=F)  %>%
  kable_styling(full_width=F) %>%
  kableExtra::pack_rows(start_row=1,end_row=4,group_label="Minimally adjusted model without CMV / VZV status.") %>%
  kableExtra::pack_rows(start_row=5,end_row=8,group_label="Unadjusted (except for HIV status) model interrogating CMV / VZV status.") %>%
  kableExtra::pack_rows(start_row=9,end_row=14,group_label="Minimally adjusted model with CMV / VZV status.") %>%
  kableExtra::pack_rows(start_row=15,end_row=25,group_label="Fully adjusted model.")
Table 10.4: Results for unadjusted, minimally adjusted and fully adjusted Poisson regression models for the number of confirmed CVD clinical events and sub-clinical CIMT derived events per 1,000 person-years. Models fitted to multiply imputed data. The estimate column below shows the reference risk for the intercept row and relative risks associated with each variable.
estimate std.error statistic df p.value
Minimally adjusted model without CMV / VZV status.
Intercept 0.0000 1.0319 -9.9050 889.9168 0.0000
Participant type PLWH 2.8423 0.5464 1.9118 889.9168 0.0562
Sex male 0.9062 0.4059 -0.2427 889.9168 0.8083
Age (in years) 1.1199 0.0144 7.8882 889.9168 0.0000
Unadjusted (except for HIV status) model interrogating CMV / VZV status.
Intercept 0.0131 0.5887 -7.3682 860.7692 0.0000
Participant type PLWH 1.3692 0.6314 0.4976 881.4587 0.6189
CMV: persistently high titres 0.8369 0.6297 -0.2828 323.5349 0.7775
VZV: persistently high titres 3.1192 0.5175 2.1984 154.8026 0.0294
Minimally adjusted model with CMV / VZV status.
Intercept 0.0000 1.0749 -9.7710 872.2838 0.0000
Participant type PLWH 2.8196 0.5511 1.8810 851.2829 0.0603
Sex male 0.7848 0.4115 -0.5890 874.5199 0.5560
Age (in years) 1.1218 0.0151 7.6209 872.1795 0.0000
CMV: persistently high titres 0.9584 0.5507 -0.0771 207.2478 0.9386
VZV: persistently high titres 2.7524 0.4480 2.2598 130.3784 0.0255
Fully adjusted model.
Intercept 0.0000 2.5688 -5.0366 861.8102 0.0000
Participant type PLWH 3.6283 0.6620 1.9467 808.9141 0.0519
Sex male 0.8698 0.4987 -0.2797 862.9852 0.7798
Age (in years) 1.1383 0.0223 5.8177 853.4860 0.0000
BMI 1.0328 0.0584 0.5522 854.2737 0.5810
Diastolic blood pressure (enrolment) 1.0505 0.0345 1.4266 869.3522 0.1541
Systolic blood pressure (enrolment) 0.9850 0.0182 -0.8295 862.9430 0.4071
Glucose (enrolment) 0.8906 0.1885 -0.6146 852.8536 0.5390
Cholesterol (enrolment) 0.8031 0.2063 -1.0633 856.4854 0.2879
CMV: persistently high titres 0.7173 0.6310 -0.5266 211.0778 0.5990
VZV: persistently high titres 2.9716 0.4836 2.2521 168.7923 0.0256

10.1 All participants

# helper functions
funFitAndSum_modClinEventsConfirmedCVD<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(as.formula(paste(sep="","numClinEventsPerParticipantCVD~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=round(digits=nDigits,exp(estimate)),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F)))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVDwithCIMT<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(as.formula(paste(sep="","numClinEventsPerParticipantCVDwithCIMT~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsCIMTonly<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(as.formula(paste(sep="","numClinEventsPerParticipantCIMTonly~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(mod)))) %>%
  mutate(
    estimateLink=estimate,
    estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
    rrCI=NA
  ) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
     
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVD.all<-funFitAndSum_modClinEventsConfirmedCVD
funFitAndSum_modClinEventsCIMTonly.all<-funFitAndSum_modClinEventsCIMTonly
funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT

# asymtomatic CIMT
tab.cimt<-tabAll.cimt %>%
  dplyr::select(!contains("hivadj")) %>%
  dplyr::filter(!grepl(term,pattern="CD4|HIV"))

# clinical CVD events
tab1.ptype<-funFitAndSum_modClinEventsConfirmedCVD("crf.ptype")
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVD("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVD("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVD("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVD("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVD("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVD("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVD("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVD("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVD("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVD("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVD("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVD("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVD("vzvStatus") # not retained as no events in some VZV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVD("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVD("vzvStatus_2levels")

tab1<-rbind(tab1.ptype,
            tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd
            tab1.cmv,
            tab1.vzv)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVD("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clinevents<-tabAll


# sub-clinical CIMT events only
tab1.ptype<-funFitAndSum_modClinEventsCIMTonly("crf.ptype")
tab1.sex<-funFitAndSum_modClinEventsCIMTonly("crf.gender")
tab1.age<-funFitAndSum_modClinEventsCIMTonly("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsCIMTonly("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsCIMTonly("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsCIMTonly("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsCIMTonly("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsCIMTonly("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsCIMTonly("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsCIMTonly("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsCIMTonly("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsCIMTonly("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsCIMTonly("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsCIMTonly("vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsCIMTonly("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsCIMTonly("vzvStatus_2levels")

tab1<-rbind(tab1.ptype,
            tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsCIMTonly("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.subclineventscimt<-tabAll

# clinical CVD events + sub-clinical CIMT events
tab1.ptype<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.ptype")
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("vzvStatus_2levels")

tab1<-rbind(tab1.ptype,
            tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithcimt<-tabAll

# combining all in a single table
#colnames(tab.cimt)<-paste(sep="_","cimt",colnames(tab.cimt))
colnames(tab.clinevents)<-paste(sep="_","clinevents",colnames(tab.clinevents))
colnames(tab.subclineventscimt)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt))
colnames(tab.clineventswithcimt)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt))

allRows<-unique(c(tab.clinevents$clinevents_term,tab.subclineventscimt$subclineventscimt_term,tab.clineventswithcimt$clineventswithcimt_term))
                
tabAll<-cbind(
  allRows,
  #tab.cimt[match(allRows,tab.cimt$cimt_term),] %>% dplyr::select(!contains("term")),
  tab.clinevents[match(allRows,tab.clinevents$clinevents_term),] %>% dplyr::select(!contains("term")),
  tab.subclineventscimt[match(allRows,tab.subclineventscimt$subclineventscimt_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithcimt[match(allRows,tab.clineventswithcimt$clineventwithcimt_term),] %>% dplyr::select(!contains("term"))
)

options(knitr.kable.NA = '')

rn<-c("Participant type: PLWH","Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: persistently high titres","VZV: persistently high titres")

tabAll %>%
  dplyr::select(!allRows) %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=c(rep(c("RR","95% CI","p"),2),rep(c("RR","95% CI","p"),4)),caption="Model summaries for models 1) fitted to clinical CVD events, 2) fitted to clinical CVD events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models for all participants). The event count models are Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from all participants.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"Clinical CVD events" = 6, "Sub-clinical CIMT events" = 6,"Clinical CVD and sub-clinical CIMT events" = 6)) %>%
  kable_styling(full_width=F)
Table 10.5: Model summaries for models 1) fitted to clinical CVD events, 2) fitted to clinical CVD events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models for all participants). The event count models are Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from all participants.
Clinical CVD events
Sub-clinical CIMT events
Clinical CVD and sub-clinical CIMT events
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Participant type: PLWH 2.10 ( 0.26,16.64) 0.48 3.98 ( 0.34,46.83) 0.27 1.18 (0.26,5.41) 0.83 3.73 ( 1.37,10.16) 0.01 1.49 (0.44,5.01) 0.52 3.63 ( 0.99,13.28) 0.05
Sex: male 2.31 ( 0.48,11.05) 0.30 2.40 ( 0.35,16.61) 0.38 0.79 (0.24,2.58) 0.70 0.33 (0.15,0.76) 0.01 1.22 (0.49,3.04) 0.66 0.87 (0.33,2.31) 0.78
Age (in years) 1.09 (1.03,1.14) 0.00 1.10 (1.02,1.19) 0.01 1.13 (1.09,1.16) 0.00 1.18 (1.14,1.23) 0.00 1.11 (1.08,1.14) 0.00 1.14 (1.09,1.19) 0.00
BMI 1.01 (0.89,1.15) 0.86 1.10 (0.94,1.28) 0.24 0.96 (0.84,1.10) 0.60 0.96 (0.86,1.07) 0.43 0.99 (0.90,1.08) 0.78 1.03 (0.92,1.16) 0.58
Diastolic blood pressure 1.03 (0.98,1.08) 0.20 1.02 (0.91,1.15) 0.74 1.04 (1.00,1.08) 0.07 1.08 (1.02,1.14) 0.01 1.03 (1.00,1.06) 0.03 1.05 (0.98,1.12) 0.15
Systolic blood pressure 1.02 (1.00,1.05) 0.06 1.00 (0.94,1.07) 0.93 1.03 (1.01,1.05) 0.01 0.97 (0.95,1.00) 0.05 1.03 (1.01,1.04) 0.00 0.99 (0.95,1.02) 0.41
Glucose 0.86 (0.43,1.71) 0.66 0.75 (0.32,1.72) 0.50 1.02 (0.78,1.33) 0.91 0.98 (0.80,1.21) 0.85 0.97 (0.74,1.29) 0.86 0.89 (0.62,1.29) 0.54
Cholesterol 0.81 (0.44,1.49) 0.50 0.65 (0.31,1.36) 0.25 1.25 (0.78,2.02) 0.35 0.96 (0.71,1.29) 0.77 1.05 (0.72,1.53) 0.82 0.80 (0.54,1.20) 0.29
CMV: persistently high titres 0.91 (0.12,6.72) 0.92 0.57 (0.06,5.62) 0.63 0.98 (0.21,4.52) 0.98 0.87 (0.34,2.23) 0.77 0.96 (0.29,3.21) 0.95 0.72 (0.21,2.47) 0.60
VZV: persistently high titres 1.37 (0.20,9.36) 0.75 1.22 (0.15,9.70) 0.85 5.46 ( 1.57,18.91) 0.01 6.38 ( 3.08,13.23) 0.00 3.16 (1.16,8.61) 0.03 2.97 (1.15,7.67) 0.03
colnames(tabAll)[colnames(tabAll)=="allRows"]<-"predictor"

tabAll.all<-tabAll[,c(1,11:13,17:19)]

#tabAll$cimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.unadj)))
#tabAll$cimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.adj)))
tabAll$clinevents_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clinevents_pvalue.unadj)))
tabAll$clinevents_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clinevents_pvalue.adj)))
tabAll$subclineventscimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$subclineventscimt_pvalue.unadj)))
tabAll$subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$subclineventscimt_pvalue.adj)))
tabAll$clineventwithcimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clineventwithcimt_pvalue.unadj)))
tabAll$clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clineventwithcimt_pvalue.adj)))
write.csv(tabAll,row.names=F,file=paste(sep="_",outPrefix,"CIMT_CVDevents_AllParticipants_Table5.csv"))

10.2 PLWH

ttt<-mice::complete(rhiccaDatWide_impMice.clinEventsConfirmed,action = "long",include = TRUE) %>%
  dplyr::mutate(numClinEventsPerParticipantCVDwithPWV=numClinEventsPerParticipantPWVonly+numClinEventsPerParticipantCVD)

rhiccaDatWide_impMice.clinEventsConfirmed<-mice::as.mids(ttt)


# helper functions
funFitAndSum_modCimt<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice %>% dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","cimtChange~cimt.cimt_enrolment",varString))))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.00",replacement="&lt;0.01"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVD<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantCVD~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVDwithCIMT<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantCVDwithCIMT~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVDwithPWV<-function(varString,filterPLWH=TRUE,nDigits=2){
  if(filterPLWH){
    mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantCVDwithPWV~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  }else{
    mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(as.formula(paste(sep="","numClinEventsPerParticipantCVDwithPWV~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  }
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsCIMTonly<-function(varString,nDigits=2){
  mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>%  dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantCIMTonly~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(mod)))) %>%
  mutate(
    estimateLink=estimate,
    estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
    rrCI=NA
  ) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
     
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsPWVonly<-function(varString,filterPLWH=TRUE,nDigits=2){
  if(filterPLWH){
    mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed %>%  dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantPWVonly~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  }else{
    mod<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(as.formula(paste(sep="","numClinEventsPerParticipantPWVonly~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  }
  
  sumObj<-summary(pool(mod)) %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(pool(mod)))) %>%
  mutate(
    estimateLink=estimate,
    estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
    rrCI=NA
  ) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
     
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

funFitAndSum_modClinEventsConfirmedCVD.hiv<-funFitAndSum_modClinEventsConfirmedCVD
funFitAndSum_modClinEventsCIMTonly.hiv<-funFitAndSum_modClinEventsCIMTonly
funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT


# asymptomatic CIMT
tab1.baseline<-funFitAndSum_modCimt("")
tab1.sex<-funFitAndSum_modCimt("+crf.gender")
tab1.age<-funFitAndSum_modCimt("+crf.age")
tab1.smoke<-funFitAndSum_modCimt("+crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modCimt("+crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modCimt("+physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modCimt("+physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modCimt("+physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modCimt("+physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modCimt("+lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modCimt("+lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modCimt("+eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modCimt("+cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modCimt("+vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modCimt("+cmvStatus_2levels") 
tab1.vzv<-funFitAndSum_modCimt("+vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modCimt("+lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modCimt("+lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modCimt("+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab1<-rbind(tab1.baseline,
            tab1.sex %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.age %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.smoke %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.alcohol %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.bmi %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.diabp %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.sysbp %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.glucose %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.cholesterol %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.ckd %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.cmv %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.vzv %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.cd4base %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.cd4change %>% dplyr::filter(term!="cimt.cimt_enrolment"),
            tab1.vl %>% dplyr::filter(term!="cimt.cimt_enrolment")
)
tab1$term<-as.character(tab1$term)

tab2<-tabAll.cimt %>%
  dplyr::select(c(term,contains("hivadj"))) %>%
  dplyr::filter(!grepl(term,pattern="ptype"))

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,coef.unadj=NA,SE.unadj=NA,pvalue.unadj=NA,coef.adj=NA,SE.adj=NA,pvalue.adj=NA)

tabAll$coef.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$SE.unadj<-tab1$std.error[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$coef.adj<-tab2$coefficient.hivadj[match(tabAll$term,tab2$term)]
tabAll$SE.adj<-tab2$SE.hivadj[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$pvalue.hivadj[match(tabAll$term,tab2$term)]

tab.cimt<-tabAll

# clinical CVD events
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVD("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVD("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVD("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVD("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVD("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVD("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVD("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVD("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVD("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVD("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVD("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVD("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVD("vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVD("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVD("vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modClinEventsConfirmedCVD("lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modClinEventsConfirmedCVD("lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modClinEventsConfirmedCVD("log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab1<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv,
            tab1.cd4base,
            tab1.cd4change,
            tab1.vl)
tab1$term<-as.character(tab1$term)

tab1.nocd4<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv)
tab1.nocd4$term<-as.character(tab1.nocd4$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVD("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab2$term<-as.character(tab2$term)

tab2.nocd4<-funFitAndSum_modClinEventsConfirmedCVD("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2.nocd4$term<-as.character(tab2.nocd4$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

allRows.nocd4<-setdiff(unique(c(tab1.nocd4$term,tab2.nocd4$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clinevents<-tabAll

tabAll.nocd4<-data.frame(term=allRows.nocd4,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll.nocd4$rr.unadj<-tab1.nocd4$estimate[match(tabAll.nocd4$term,tab1$term)]
tabAll.nocd4$rrCI.unadj<-tab1.nocd4$rrCI[match(tabAll.nocd4$term,tab1$term)]
tabAll.nocd4$pvalue.unadj<-tab1.nocd4$p.value[match(tabAll.nocd4$term,tab1$term)]

tabAll.nocd4$rr.adj<-tab2.nocd4$estimate[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$rrCI.adj<-tab2.nocd4$rrCI[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$pvalue.adj<-tab2.nocd4$p.value[match(tabAll.nocd4$term,tab2.nocd4$term)]

tab.clinevents.nocd4<-tabAll.nocd4

# sub-clinical CIMT events only
tab1.sex<-funFitAndSum_modClinEventsCIMTonly("crf.gender")
tab1.age<-funFitAndSum_modClinEventsCIMTonly("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsCIMTonly("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsCIMTonly("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsCIMTonly("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsCIMTonly("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsCIMTonly("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsCIMTonly("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsCIMTonly("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsCIMTonly("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsCIMTonly("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsCIMTonly("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsCIMTonly("vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsCIMTonly("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsCIMTonly("vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modClinEventsCIMTonly("lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modClinEventsCIMTonly("lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modClinEventsCIMTonly("log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab1<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv,
            tab1.cd4base,
            tab1.cd4change,
            tab1.vl)
tab1$term<-as.character(tab1$term)

tab1.nocd4<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv)
tab1.nocd4$term<-as.character(tab1.nocd4$term)

tab2<-funFitAndSum_modClinEventsCIMTonly("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab2$term<-as.character(tab2$term)

tab2.nocd4<-funFitAndSum_modClinEventsCIMTonly("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2.nocd4$term<-as.character(tab2.nocd4$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

allRows.nocd4<-setdiff(unique(c(tab1.nocd4$term,tab2.nocd4$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tabAll.nocd4<-data.frame(term=allRows.nocd4,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll.nocd4$rr.unadj<-tab1.nocd4$estimate[match(tabAll.nocd4$term,tab1.nocd4$term)]
tabAll.nocd4$rrCI.unadj<-tab1.nocd4$rrCI[match(tabAll.nocd4$term,tab1.nocd4$term)]
tabAll.nocd4$pvalue.unadj<-tab1.nocd4$p.value[match(tabAll.nocd4$term,tab1.nocd4$term)]

tabAll.nocd4$rr.adj<-tab2.nocd4$estimate[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$rrCI.adj<-tab2.nocd4$rrCI[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$pvalue.adj<-tab2.nocd4$p.value[match(tabAll.nocd4$term,tab2.nocd4$term)]

tab.subclineventscimt<-tabAll

tab.subclineventscimt.nocd4<-tabAll.nocd4

# clinical CVD events + sub-clinical CIMT events
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.smoke") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.alcohol") # not retained: no events in risk group --> ridiculous / unstable coefficient
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("eGFR_existingCKD") # not retained: no events in risk group --> ridiculous / unstable coefficient
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("cmvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("vzvStatus") # not retained as no events in some CMV groups --> ridiculous / unstable coefficient for that group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")

tab1<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv,
            tab1.cd4base,
            tab1.cd4change,
            tab1.vl)
tab1$term<-as.character(tab1$term)

tab1.nocd4<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv)
tab1.nocd4$term<-as.character(tab1.nocd4$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab2$term<-as.character(tab2$term)

tab2.nocd4<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2.nocd4$term<-as.character(tab2.nocd4$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

allRows.nocd4<-setdiff(unique(c(tab1.nocd4$term,tab2.nocd4$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithcimt<-tabAll

tabAll.nocd4<-data.frame(term=allRows.nocd4,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll.nocd4$rr.unadj<-tab1.nocd4$estimate[match(tabAll.nocd4$term,tab1.nocd4$term)]
tabAll.nocd4$rrCI.unadj<-tab1.nocd4$rrCI[match(tabAll.nocd4$term,tab1.nocd4$term)]
tabAll.nocd4$pvalue.unadj<-tab1.nocd4$p.value[match(tabAll.nocd4$term,tab1.nocd4$term)]

tabAll.nocd4$rr.adj<-tab2.nocd4$estimate[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$rrCI.adj<-tab2.nocd4$rrCI[match(tabAll.nocd4$term,tab2.nocd4$term)]
tabAll.nocd4$pvalue.adj<-tab2.nocd4$p.value[match(tabAll.nocd4$term,tab2.nocd4$term)]

tab.clineventswithcimt.nocd4<-tabAll.nocd4

# combining all in a single table
#colnames(tab.cimt)<-paste(sep="_","cimt",colnames(tab.cimt))
colnames(tab.clinevents)<-paste(sep="_","clinevents",colnames(tab.clinevents))
colnames(tab.subclineventscimt)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt))
colnames(tab.clineventswithcimt)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt))

allRows<-unique(c(tab.clinevents$subclineventscimt_term,tab.subclineventscimt$subclineventscimt_term,tab.clineventswithcimt$clineventswithcimt_term))
                
tabAll<-cbind(
  allRows,
  #tab.cimt[match(allRows,tab.cimt$cimt_term),] %>% dplyr::select(!contains("term")),
  tab.clinevents[match(allRows,tab.clinevents$clinevents_term),] %>% dplyr::select(!contains("term")),
  tab.subclineventscimt[match(allRows,tab.subclineventscimt$subclineventscimt_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithcimt[match(allRows,tab.clineventswithcimt$clineventwithcimt_term),] %>% dplyr::select(!contains("term"))
)

colnames(tab.clinevents.nocd4)<-paste(sep="_","clinevents",colnames(tab.clinevents.nocd4))
colnames(tab.subclineventscimt.nocd4)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt.nocd4))
colnames(tab.clineventswithcimt.nocd4)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt.nocd4))

allRows.nocd4<-unique(c(tab.clinevents.nocd4$clinevents_term,tab.subclineventscimt.nocd4$subclineventscimt_term,tab.clineventswithcimt.nocd4$clineventswithcimt_term))
                
tabAll.nocd4<-cbind(
  allRows.nocd4,
  #tab.cimt[match(allRows,tab.cimt$cimt_term),] %>% dplyr::select(!contains("term")),
  tab.clinevents.nocd4[match(allRows.nocd4,tab.clinevents.nocd4$clinevents_term),] %>% dplyr::select(!contains("term")),
  tab.subclineventscimt.nocd4[match(allRows.nocd4,tab.subclineventscimt.nocd4$subclineventscimt_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithcimt.nocd4[match(allRows.nocd4,tab.clineventswithcimt.nocd4$clineventwithcimt_term),] %>% dplyr::select(!contains("term"))
)

options(knitr.kable.NA = '')

rn<-c("Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: persistently high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline at 24 months)","log viral load (baseline)")

tabAll %>%
  dplyr::select(!allRows) %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=c(rep(c("RR","95% CI","p"),2),rep(c("RR","95% CI","p"),4)),caption="Model summaries for models for PLWH only 1) fitted to clinical CVD events only, 2) fitted to sub-clinical CIMT events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models). The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"Clinical CVD events" = 6, "Sub-clinical CIMT events" = 6,"Clinical CVD and sub-clinical CIMT events" = 6)) %>%
  kable_styling(full_width=F)
Table 10.6: Model summaries for models for PLWH only 1) fitted to clinical CVD events only, 2) fitted to sub-clinical CIMT events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models). The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from PLWH only.
Clinical CVD events
Sub-clinical CIMT events
Clinical CVD and sub-clinical CIMT events
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Sex: male 1.79 (0.36,8.80) 0.48 2.27 ( 0.43,11.99) 0.33 0.48 (0.13,1.76) 0.27 0.16 (0.06,0.40) 0.00 0.85 (0.33,2.21) 0.74 0.68 (0.26,1.77) 0.42
Age (in years) 1.08 (1.02,1.15) 0.01 1.10 (1.03,1.18) 0.01 1.13 (1.09,1.17) 0.00 1.18 (1.13,1.24) 0.00 1.11 (1.07,1.14) 0.00 1.12 (1.07,1.17) 0.00
BMI 1.03 (0.90,1.18) 0.66 1.09 (0.95,1.25) 0.21 1.02 (0.89,1.17) 0.75 1.04 (0.94,1.15) 0.45 1.03 (0.93,1.13) 0.59 1.05 (0.95,1.16) 0.32
Diastolic blood pressure 1.01 (0.96,1.07) 0.61 1.04 (0.93,1.17) 0.47 1.04 (1.00,1.08) 0.04 1.06 (1.00,1.13) 0.05 1.03 (1.00,1.06) 0.07 1.04 (0.97,1.12) 0.26
Systolic blood pressure 1.01 (0.98,1.04) 0.38 0.99 (0.93,1.05) 0.73 1.03 (1.01,1.05) 0.01 0.99 (0.96,1.02) 0.69 1.02 (1.01,1.04) 0.01 0.99 (0.96,1.03) 0.72
Glucose 0.82 (0.37,1.78) 0.61 0.70 (0.35,1.41) 0.32 1.03 (0.80,1.33) 0.82 1.00 (0.83,1.21) 0.97 0.98 (0.74,1.31) 0.90 0.90 (0.62,1.29) 0.56
Cholesterol 0.83 (0.41,1.68) 0.61 0.74 (0.37,1.48) 0.39 1.23 (0.70,2.18) 0.47 0.65 (0.45,0.94) 0.02 1.04 (0.67,1.63) 0.86 0.74 (0.48,1.14) 0.17
CMV: persistently high titres 0.83 (0.11,6.34) 0.85 0.44 (0.06,3.20) 0.42 0.99 (0.21,4.75) 0.99 0.87 (0.33,2.32) 0.78 0.93 (0.27,3.19) 0.90 0.68 (0.21,2.22) 0.53
VZV: persistently high titres 0.03 (0.00, Inf) 1.00 0.03 (0.00, Inf) 1.00 7.95 ( 1.87,33.89) 0.01 13.84 ( 5.93,32.31) 0.00 2.96 (0.98,8.96) 0.06 3.08 (1.16,8.17) 0.03
CD4 (baseline) 0.99 (0.99,1.00) 0.06 0.99 (0.99,1.00) 0.08 1.00 (0.99,1.00) 0.66 1.00 (1.00,1.00) 0.31 1.00 (0.99,1.00) 0.14 1.00 (0.99,1.00) 0.11
CD4 (change from baseline at 24 months) 1.00 (1.00,1.01) 0.73 1.00 (0.99,1.01) 0.63 1.00 (1.00,1.00) 0.88 1.00 (1.00,1.00) 0.54 1.00 (1.00,1.00) 0.88 1.00 (1.00,1.00) 0.82
log viral load (baseline) 1.56 (0.77,3.18) 0.22 1.37 (0.65,2.86) 0.41 0.89 (0.59,1.34) 0.57 0.80 (0.61,1.06) 0.12 1.08 (0.75,1.56) 0.68 0.96 (0.67,1.38) 0.81
colnames(tabAll)[colnames(tabAll)=="allRows"]<-"predictor"

tabAll.PLWH.cd4<-tabAll[,c(1,11:13,17:19)]

#tabAll$cimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.unadj)))
#tabAll$cimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.adj)))
tabAll$clinevents_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clinevents_pvalue.unadj)))
tabAll$clinevents_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clinevents_pvalue.adj)))
tabAll$subclineventscimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$subclineventscimt_pvalue.unadj)))
tabAll$subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$subclineventscimt_pvalue.adj)))
tabAll$clineventwithcimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clineventwithcimt_pvalue.unadj)))
tabAll$clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$clineventwithcimt_pvalue.adj)))
write.csv(tabAll,row.names=F,file=paste(sep="_",outPrefix,"CIMT_CVDevents_PLWH.csv"))

10.2.1 Without CD4

rn.nocd4<-c("Sex: male","Age (in years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose","Cholesterol","CMV: persistently high titres","VZV: persistently high titres")

tabAll.nocd4 %>%
  dplyr::select(!allRows.nocd4) %>%
  kableRn(digits=3,escape=F,row_names=rn.nocd4,col.names=c(rep(c("RR","95% CI","p"),2),rep(c("RR","95% CI","p"),4)),caption="Model summaries for models for PLWH only 1) fitted to clinical CVD events only, 2) fitted to sub-clinical CIMT events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models). The event count models are Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from PLWH only.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"Clinical CVD events" = 6, "Sub-clinical CIMT events" = 6,"Clinical CVD and sub-clinical CIMT events" = 6)) %>%
  kable_styling(full_width=F)
Table 10.7: Model summaries for models for PLWH only 1) fitted to clinical CVD events only, 2) fitted to sub-clinical CIMT events only and 3) fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models). The event count models are Poisson models and hence report rate ratios. Models fitted to multiply-imputed data from PLWH only.
Clinical CVD events
Sub-clinical CIMT events
Clinical CVD and sub-clinical CIMT events
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
Unadjusted models
Multiple regression model
RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Sex: male 1.79 (0.36,8.80) 0.48 2.13 ( 0.33,13.86) 0.43 0.48 (0.13,1.76) 0.27 0.17 (0.07,0.42) 0.00 0.85 (0.33,2.21) 0.74 0.66 (0.24,1.82) 0.42
Age (in years) 1.08 (1.02,1.15) 0.01 1.10 (1.02,1.19) 0.02 1.13 (1.09,1.17) 0.00 1.17 (1.13,1.22) 0.00 1.11 (1.07,1.14) 0.00 1.12 (1.07,1.18) 0.00
BMI 1.03 (0.90,1.18) 0.66 1.09 (0.94,1.26) 0.27 1.02 (0.89,1.17) 0.75 1.02 (0.92,1.13) 0.70 1.03 (0.93,1.13) 0.59 1.05 (0.94,1.17) 0.37
Diastolic blood pressure 1.01 (0.96,1.07) 0.61 1.02 (0.90,1.15) 0.76 1.04 (1.00,1.08) 0.04 1.06 (1.00,1.12) 0.06 1.03 (1.00,1.06) 0.07 1.03 (0.96,1.11) 0.41
Systolic blood pressure 1.01 (0.98,1.04) 0.38 0.99 (0.92,1.07) 0.82 1.03 (1.01,1.05) 0.01 1.00 (0.97,1.03) 0.89 1.02 (1.01,1.04) 0.01 1.00 (0.96,1.04) 0.85
Glucose 0.82 (0.37,1.78) 0.61 0.77 (0.35,1.71) 0.52 1.03 (0.80,1.33) 0.82 1.01 (0.85,1.21) 0.88 0.98 (0.74,1.31) 0.90 0.91 (0.64,1.30) 0.60
Cholesterol 0.83 (0.41,1.68) 0.61 0.74 (0.35,1.58) 0.44 1.23 (0.70,2.18) 0.47 0.69 (0.49,0.97) 0.03 1.04 (0.67,1.63) 0.86 0.73 (0.47,1.14) 0.17
CMV: persistently high titres 0.83 (0.11,6.34) 0.85 0.67 (0.08,6.01) 0.72 0.99 (0.21,4.75) 0.99 0.79 (0.31,2.02) 0.63 0.93 (0.27,3.19) 0.90 0.76 (0.22,2.60) 0.66
VZV: persistently high titres 0.03 (0.00, Inf) 1.00 0.03 (0.00, Inf) 1.00 7.95 ( 1.87,33.89) 0.01 13.64 ( 6.02,30.91) 0.00 2.96 (0.98,8.96) 0.06 3.28 (1.16,9.25) 0.03
colnames(tabAll.nocd4)[colnames(tabAll.nocd4)=="allRows"]<-"predictor"

tabAll.PLWH.nocd4<-tabAll.nocd4[,c(1,14:19)]

#tabAll$cimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.unadj)))
#tabAll$cimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll$cimt_pvalue.adj)))
tabAll.nocd4$clinevents_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$clinevents_pvalue.unadj)))
tabAll.nocd4$clinevents_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$clinevents_pvalue.adj)))
tabAll.nocd4$subclineventscimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$subclineventscimt_pvalue.unadj)))
tabAll.nocd4$subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$subclineventscimt_pvalue.adj)))
tabAll.nocd4$clineventwithcimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$clineventwithcimt_pvalue.unadj)))
tabAll.nocd4$clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*>0",replace="0",tabAll.nocd4$clineventwithcimt_pvalue.adj)))

write.csv(tabAll.nocd4,row.names=F,file=paste(sep="_",outPrefix,"CIMT_CVDevents_PLWH.csv"))

10.2.1.1 Sensitivity analysis

Here we do a sensitivity analysis (for PLWH only) for the multivariable regression model (without CD4) showing an association between pVZV, respectively pCMV, and CVD events (clinical and sub-clinical CIMT).

To note that the main analysis made use of multiply imputed data and uses all available data to as best as possible impute the missing VZV status values, all the while taking into account the uncertainty inherent to the imputation itself.

For the sensitivity analysis we will manually impute all missing VZV statuses to “not persistently high titres” (scenario 1 - best case) and to “persistently high titres” (scenario 2 - worst case) respectively, and similarly for the sensitivity analysis for CMV status.

funFitAndSum_modClinEventsConfirmedCVDwithCIMT_SA<-function(varString,exp,scen,nDigits=2){
  tt<-complete(rhiccaDatWide_impMice.clinEventsConfirmed,include=TRUE,action="long")
  idxMVvzv<-which(is.na(tt$vzvStatus[tt$.imp==0]))
  idxMVcmv<-which(is.na(tt$cmvStatus[tt$.imp==0]))
  for(m in 1:max(tt$.imp)){
    if(scen=="worst"){
      if(exp=="vzv"){tt$vzvStatus[tt$.imp==m][idxMVvzv]<-"persistently high titres"}
      if(exp=="cmv"){tt$cmvStatus[tt$.imp==m][idxMVcmv]<-"persistently high titres"}
    }
    if(scen=="best"){
      if(exp=="vzv"){tt$vzvStatus[tt$.imp==m][idxMVvzv]<-"persistently low titres"}
      if(exp=="cmv"){tt$cmvStatus[tt$.imp==m][idxMVcmv]<-"persistently low titres"}
    }
  }
  tt<-as.mids(tt)
  
  mod<-with(tt %>% dplyr::filter(crf.ptype=="Patient"),glm(as.formula(paste(sep="","numClinEventsPerParticipantCVDwithCIMT~",varString)),offset=obsTime/(1000*365.25),family="quasipoisson"))
  
  sumObj<-summary(pool(mod)) %>%
    as.data.frame() %>%
    mutate(rownum=1:nrow(summary(pool(mod)))) %>%
    mutate(
      estimateLink=estimate,
      estimate=format(nsmall=nDigits,round(digits=nDigits,exp(estimate))),
      rrCI=NA
    ) %>%
    mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=T),cell_spec(format(nsmall=nDigits,round(digits=nDigits,p.value)),bold=F))) %>%
    mutate(p.value=gsub(p.value,pattern="0.000",replacement="&lt;0.001"))
  
  for(j in 1:nrow(sumObj)){
    sumObj$rrCI[j]<-paste(sep="","(",paste(collapse=",",format(nsmall=nDigits,round(digits=nDigits,c(exp(sumObj$estimateLink[j]-qnorm(0.975)*sumObj$std.error[j]),exp(sumObj$estimateLink[j]+qnorm(0.975)*sumObj$std.error[j]))))),")")
  }
  
  sumObj<-sumObj %>% dplyr::select(!estimateLink)
  
  return(sumObj)         
}

tab2.nocd4.sa.worst.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT_SA("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)",scen="worst",exp="vzv")
tab2.nocd4.sa.worst.vzv$term<-as.character(tab2.nocd4.sa.worst.vzv$term)

tab2.nocd4.sa.best.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT_SA("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)",scen="best",exp="vzv")
tab2.nocd4.sa.best.vzv$term<-as.character(tab2.nocd4.sa.best.vzv$term)

tab2.nocd4.sa.worst.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT_SA("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)",scen="worst",exp="cmv")
tab2.nocd4.sa.worst.cmv$term<-as.character(tab2.nocd4.sa.worst.cmv$term)

tab2.nocd4.sa.best.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT_SA("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)",scen="best",exp="cmv")
tab2.nocd4.sa.best.cmv$term<-as.character(tab2.nocd4.sa.best.cmv$term)

WORST case scenario - VZV

tab2.nocd4.sa.worst.vzv %>%
  kableRn(digits=3,escape=F,caption="WORST case scenario: every missing VZV status = persistently high VZV. The association with VZV is no longer statistically significant but this is hardly surprising as over half of the data will now be recorded as having pVZV.") %>%
  kable_styling()
Table 10.8: WORST case scenario: every missing VZV status = persistently high VZV. The association with VZV is no longer statistically significant but this is hardly surprising as over half of the data will now be recorded as having pVZV.
term estimate std.error statistic df p.value rownum rrCI
(Intercept) 0.00 2.520 -4.136 664.291 0.00 1 (0.00,0.00)
crf.genderMale 0.68 0.491 -0.799 684.791 0.42 2 (0.26,1.77)
crf.age 1.12 0.023 4.940 687.357 0.00 3 (1.07,1.17)
physio.bmi_enrolment 1.05 0.051 0.991 638.375 0.32 4 (0.95,1.16)
physio.bp_dia_enrolment 1.04 0.036 1.121 674.430 0.26 5 (0.97,1.12)
physio.bp_sys_enrolment 0.99 0.019 -0.361 677.880 0.72 6 (0.96,1.03)
lims.Glucose_enrolment 0.90 0.187 -0.589 676.723 0.56 7 (0.62,1.29)
lims.Cholesterol_enrolment 0.74 0.223 -1.367 687.405 0.17 8 (0.48,1.14)
cmvStatus_2levelspersistently high titres 0.68 0.602 -0.634 148.979 0.53 9 (0.21,2.22)
vzvStatus_2levelspersistently high titres 3.08 0.498 2.263 113.974 0.03 10 (1.16,8.17)
lims.CD4_Absolute_enrolment 1.00 0.002 -1.620 689.392 0.11 11 (0.99,1.00)
lims.CD4_Absolute_changeFromBaselineAt24Months 1.00 0.002 0.232 156.559 0.82 12 (1.00,1.00)
log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment) 0.96 0.185 -0.237 681.137 0.81 13 (0.67,1.38)

BEST case scenario - VZV

tab2.nocd4.sa.best.vzv %>%
  kableRn(digits=3,escape=F,caption="BEST case scenario: every missing VZV status = persistently low VZV. The association with VZV remains statistically significant - in fact becomes slightly stronger.") %>%
  kable_styling() 
Table 10.9: BEST case scenario: every missing VZV status = persistently low VZV. The association with VZV remains statistically significant - in fact becomes slightly stronger.
term estimate std.error statistic df p.value rownum rrCI
(Intercept) 0.00 2.520 -4.136 664.291 0.00 1 (0.00,0.00)
crf.genderMale 0.68 0.491 -0.799 684.791 0.42 2 (0.26,1.77)
crf.age 1.12 0.023 4.940 687.357 0.00 3 (1.07,1.17)
physio.bmi_enrolment 1.05 0.051 0.991 638.375 0.32 4 (0.95,1.16)
physio.bp_dia_enrolment 1.04 0.036 1.121 674.430 0.26 5 (0.97,1.12)
physio.bp_sys_enrolment 0.99 0.019 -0.361 677.880 0.72 6 (0.96,1.03)
lims.Glucose_enrolment 0.90 0.187 -0.589 676.723 0.56 7 (0.62,1.29)
lims.Cholesterol_enrolment 0.74 0.223 -1.367 687.405 0.17 8 (0.48,1.14)
cmvStatus_2levelspersistently high titres 0.68 0.602 -0.634 148.979 0.53 9 (0.21,2.22)
vzvStatus_2levelspersistently high titres 3.08 0.498 2.263 113.974 0.03 10 (1.16,8.17)
lims.CD4_Absolute_enrolment 1.00 0.002 -1.620 689.392 0.11 11 (0.99,1.00)
lims.CD4_Absolute_changeFromBaselineAt24Months 1.00 0.002 0.232 156.559 0.82 12 (1.00,1.00)
log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment) 0.96 0.185 -0.237 681.137 0.81 13 (0.67,1.38)

WORST case scenario - CMV

tab2.nocd4.sa.worst.cmv %>%
  kableRn(digits=3,escape=F,caption="WORST case scenario: every missing CMV status = persistently high CMV. The association with CMV remains insignificant (and not that the association with VZV remains largely unchanged).") %>%
  kable_styling()
Table 10.10: WORST case scenario: every missing CMV status = persistently high CMV. The association with CMV remains insignificant (and not that the association with VZV remains largely unchanged).
term estimate std.error statistic df p.value rownum rrCI
(Intercept) 0.00 2.520 -4.136 664.291 0.00 1 (0.00,0.00)
crf.genderMale 0.68 0.491 -0.799 684.791 0.42 2 (0.26,1.77)
crf.age 1.12 0.023 4.940 687.357 0.00 3 (1.07,1.17)
physio.bmi_enrolment 1.05 0.051 0.991 638.375 0.32 4 (0.95,1.16)
physio.bp_dia_enrolment 1.04 0.036 1.121 674.430 0.26 5 (0.97,1.12)
physio.bp_sys_enrolment 0.99 0.019 -0.361 677.880 0.72 6 (0.96,1.03)
lims.Glucose_enrolment 0.90 0.187 -0.589 676.723 0.56 7 (0.62,1.29)
lims.Cholesterol_enrolment 0.74 0.223 -1.367 687.405 0.17 8 (0.48,1.14)
cmvStatus_2levelspersistently high titres 0.68 0.602 -0.634 148.979 0.53 9 (0.21,2.22)
vzvStatus_2levelspersistently high titres 3.08 0.498 2.263 113.974 0.03 10 (1.16,8.17)
lims.CD4_Absolute_enrolment 1.00 0.002 -1.620 689.392 0.11 11 (0.99,1.00)
lims.CD4_Absolute_changeFromBaselineAt24Months 1.00 0.002 0.232 156.559 0.82 12 (1.00,1.00)
log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment) 0.96 0.185 -0.237 681.137 0.81 13 (0.67,1.38)

BEST case scenario - CMV

tab2.nocd4.sa.best.cmv %>%
  kableRn(digits=3,escape=F,caption="BEST case scenario: every missing CMV status = persistently low CMV. The association with CMV remains insignificant (and not that the association with VZV remains largely unchanged).") %>%
  kable_styling()
Table 10.11: BEST case scenario: every missing CMV status = persistently low CMV. The association with CMV remains insignificant (and not that the association with VZV remains largely unchanged).
term estimate std.error statistic df p.value rownum rrCI
(Intercept) 0.00 2.520 -4.136 664.291 0.00 1 (0.00,0.00)
crf.genderMale 0.68 0.491 -0.799 684.791 0.42 2 (0.26,1.77)
crf.age 1.12 0.023 4.940 687.357 0.00 3 (1.07,1.17)
physio.bmi_enrolment 1.05 0.051 0.991 638.375 0.32 4 (0.95,1.16)
physio.bp_dia_enrolment 1.04 0.036 1.121 674.430 0.26 5 (0.97,1.12)
physio.bp_sys_enrolment 0.99 0.019 -0.361 677.880 0.72 6 (0.96,1.03)
lims.Glucose_enrolment 0.90 0.187 -0.589 676.723 0.56 7 (0.62,1.29)
lims.Cholesterol_enrolment 0.74 0.223 -1.367 687.405 0.17 8 (0.48,1.14)
cmvStatus_2levelspersistently high titres 0.68 0.602 -0.634 148.979 0.53 9 (0.21,2.22)
vzvStatus_2levelspersistently high titres 3.08 0.498 2.263 113.974 0.03 10 (1.16,8.17)
lims.CD4_Absolute_enrolment 1.00 0.002 -1.620 689.392 0.11 11 (0.99,1.00)
lims.CD4_Absolute_changeFromBaselineAt24Months 1.00 0.002 0.232 156.559 0.82 12 (1.00,1.00)
log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment) 0.96 0.185 -0.237 681.137 0.81 13 (0.67,1.38)

10.2.2 Table 3 for manuscript

10.2.2.1 CIMT

# rnames<-c("crf.ptypePatient",tabAll.PLWH.nocd4[,1],"lims.CD4_Absolute_enrolment","lims.CD4_Absolute_changeFromBaselineAt24Months")
# rn<-c("Participant type: PLWH","Sex: male","Age (years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: persistently high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline at 24 months)")
# 
# colnames(tabAll.PLWH.nocd4)<-paste(sep="","PLWHnocd4_",colnames(tabAll.PLWH.nocd4))
# colnames(tabAll.PLWH.cd4)<-paste(sep="","PLWHcd4_",colnames(tabAll.PLWH.cd4))
# colnames(tabAll.all)<-paste(sep="","all_",colnames(tabAll.all))
# 
# tabAll.tab5manu<-cbind(
#   rnames,
#   tabAll.PLWH.cd4[match(rnames,tabAll.PLWH.cd4[,1]),2:4],
#   tabAll.PLWH.nocd4[match(rnames,tabAll.PLWH.nocd4[,1]),5:7],
#   tabAll.PLWH.cd4[match(rnames,tabAll.PLWH.cd4[,1]),5:7],
#   tabAll.all[match(rnames,tabAll.all[,1]),-1]
# )
# 
# tabAll.tab5manu %>%
#   dplyr::select(!"rnames") %>%
#   kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("RR","95% CI","p"),5),caption="Model summaries for models fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models) for 1) PLWH and 2) all participants. The event count models are Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.") %>%
#   #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
#   add_header_above(header=c(" "=1,"Unadjusted models" = 3, "Multiple regression model (without CD4)" = 3, "Multiple regression model (with CD4)" = 3,"Unadjusted models" = 3, "Multiple regression model" = 3)) %>%
#   add_header_above(header=c(" "=1,"PLWH" = 9,"All participants" = 6)) %>%
#   kable_styling(full_width=F)
# 
# tabAll.tab5manu$PLWHcd4_clineventwithcimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab5manu$PLWHcd4_clineventwithcimt_pvalue.unadj)))
# tabAll.tab5manu$PLWHnocd4_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab5manu$PLWHnocd4_clineventwithcimt_pvalue.adj)))
# tabAll.tab5manu$PLWHcd4_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab5manu$PLWHcd4_clineventwithcimt_pvalue.adj)))
# tabAll.tab5manu$all_clineventwithcimt_pvalue.unadj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab5manu$all_clineventwithcimt_pvalue.unadj)))
# tabAll.tab5manu$all_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab5manu$all_clineventwithcimt_pvalue.adj)))
# 
# write.csv(tabAll.tab5manu,row.names=F,file=paste(sep="_",outPrefix,"CIMT_CVDevents_PLWH_All_Table3.csv"))
rnames<-c("crf.ptypePatient",tabAll.PLWH.nocd4[,1],"lims.CD4_Absolute_enrolment","lims.CD4_Absolute_changeFromBaselineAt24Months","log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
rn<-c("Participant type: PLWH","Sex: male","Age (years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: persistently high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline at 24 months)","log10 viral load (baseline)")

#colnames(tabAll.PLWH.nocd4)<-paste(sep="","PLWHnocd4_",colnames(tabAll.PLWH.nocd4))
colnames(tabAll.PLWH.cd4)<-paste(sep="","PLWHcd4_",colnames(tabAll.PLWH.cd4))
colnames(tabAll.all)<-paste(sep="","all_",colnames(tabAll.all))

tabAll.tab3manu<-cbind(
  rnames,
  #tabAll.PLWH.cd4[match(rnames,tabAll.PLWH.cd4[,1]),2:4],
  #tabAll.PLWH.nocd4[match(rnames,tabAll.PLWH.nocd4[,1]),5:7],
  tabAll.PLWH.cd4[match(rnames,tabAll.PLWH.cd4[,1]),-1],
  tabAll.all[match(rnames,tabAll.all[,1]),-1]
)

tabAll.tab3manu %>%
  dplyr::select(!"rnames") %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("RR","95% CI","p"),4),caption="Model summaries for models fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models) for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Multiple regression model" = 3, "Multiple regression model" = 3,"Multiple regression model" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"PLWH" = 6,"All participants" = 6)) %>%
  kable_styling(full_width=F)
Table 10.12: Model summaries for models fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models) for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.
PLWH
All participants
Multiple regression model
Multiple regression model
Multiple regression model
Multiple regression model
RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Participant type: PLWH 3.73 ( 1.37,10.16) 0.01 3.63 ( 0.99,13.28) 0.05
Sex: male 0.16 (0.06,0.40) 0.00 0.68 (0.26,1.77) 0.42 0.33 (0.15,0.76) 0.01 0.87 (0.33,2.31) 0.78
Age (years) 1.18 (1.13,1.24) 0.00 1.12 (1.07,1.17) 0.00 1.18 (1.14,1.23) 0.00 1.14 (1.09,1.19) 0.00
BMI 1.04 (0.94,1.15) 0.45 1.05 (0.95,1.16) 0.32 0.96 (0.86,1.07) 0.43 1.03 (0.92,1.16) 0.58
Diastolic blood pressure 1.06 (1.00,1.13) 0.05 1.04 (0.97,1.12) 0.26 1.08 (1.02,1.14) 0.01 1.05 (0.98,1.12) 0.15
Systolic blood pressure 0.99 (0.96,1.02) 0.69 0.99 (0.96,1.03) 0.72 0.97 (0.95,1.00) 0.05 0.99 (0.95,1.02) 0.41
Glucose (baseline) 1.00 (0.83,1.21) 0.97 0.90 (0.62,1.29) 0.56 0.98 (0.80,1.21) 0.85 0.89 (0.62,1.29) 0.54
Cholesterol (baseline) 0.65 (0.45,0.94) 0.02 0.74 (0.48,1.14) 0.17 0.96 (0.71,1.29) 0.77 0.80 (0.54,1.20) 0.29
CMV: persistently high titres 0.87 (0.33,2.32) 0.78 0.68 (0.21,2.22) 0.53 0.87 (0.34,2.23) 0.77 0.72 (0.21,2.47) 0.60
VZV: persistently high titres 13.84 ( 5.93,32.31) 0.00 3.08 (1.16,8.17) 0.03 6.38 ( 3.08,13.23) 0.00 2.97 (1.15,7.67) 0.03
CD4 (baseline) 1.00 (1.00,1.00) 0.31 1.00 (0.99,1.00) 0.11
CD4 (change from baseline at 24 months) 1.00 (1.00,1.00) 0.54 1.00 (1.00,1.00) 0.82
log10 viral load (baseline) 0.80 (0.61,1.06) 0.12 0.96 (0.67,1.38) 0.81
tabAll.tab3manu$PLWHcd4_subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWHcd4_subclineventscimt_pvalue.adj)))
tabAll.tab3manu$PLWHcd4_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWHcd4_clineventwithcimt_pvalue.adj)))
tabAll.tab3manu$all_subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_subclineventscimt_pvalue.adj)))
tabAll.tab3manu$all_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_clineventwithcimt_pvalue.adj)))

write.csv(tabAll.tab3manu,row.names=F,file=paste(sep="_",outPrefix,"CIMT_SubAndClinCVDevents_PLWH_All_Table3.csv"))

10.2.2.2 CIMT (with ART)

# All participants
# tt<-complete(action="long",include=T,rhiccaDatWide_impMice.clinEventsConfirmed)
# tt<-tt %>%
#   dplyr::mutate(crf.artRegimen.2levels.bkp=crf.artRegimen.2levels) %>%
#   dplyr::mutate(
#       crf.artRegimen.2levels=case_when(
#       crf.ptype=="Patient"~crf.artRegimen.2levels.bkp,
#       crf.ptype=="Control"~levels(crf.artRegimen.2levels.bkp)[1]
#     )
#   )
# rhiccaDatWide_impMice.clinEventsConfirmed<-as.mids(tt)

## sub-clinical CIMT events only
tab1.ptype<-funFitAndSum_modClinEventsCIMTonly.all("crf.ptype")
tab1.sex<-funFitAndSum_modClinEventsCIMTonly.all("crf.gender")
tab1.age<-funFitAndSum_modClinEventsCIMTonly.all("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsCIMTonly.all("crf.smoke") # ridiculous / unstable model coefficients due to no events in one group
tab1.alcohol<-funFitAndSum_modClinEventsCIMTonly.all("crf.alcohol") # ridiculous / unstable model coefficients due to no events in one group
tab1.waisthip<-funFitAndSum_modClinEventsCIMTonly.all("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsCIMTonly.all("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsCIMTonly.all("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsCIMTonly.all("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsCIMTonly.all("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsCIMTonly.all("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsCIMTonly.all("eGFR_existingCKD") # ridiculous / unstable model coefficients due to no events in one group
#tab1.cmv<-funFitAndSum_modClinEventsCIMTonly.all("cmvStatus") # ridiculous / unstable model coefficients due to no events in one group
#tab1.vzv<-funFitAndSum_modClinEventsCIMTonly.all("vzvStatus") # ridiculous / unstable model coefficients due to no events in one group
tab1.cmv<-funFitAndSum_modClinEventsCIMTonly.all("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsCIMTonly.all("vzvStatus_2levels")

tab1<-rbind(tab1.ptype,
            tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv
)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsCIMTonly.all("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.subclineventscimt<-tabAll

## clinical CVD events + sub-clinical CIMT events
tab1.ptype<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.ptype")
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.smoke") # ridiculous / unstable model coefficients due to no events in one group
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.alcohol") # ridiculous / unstable model coefficients due to no events in one group
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("eGFR_existingCKD") # ridiculous / unstable model coefficients due to no events in one group
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("cmvStatus") # ridiculous / unstable model coefficients due to no events in one group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("vzvStatus") # ridiculous / unstable model coefficients due to no events in one group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("vzvStatus_2levels")

tab1<-rbind(tab1.ptype,
            tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv
)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.all("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithcimt<-tabAll

## combining all in a single table
colnames(tab.subclineventscimt)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt))
colnames(tab.clineventswithcimt)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt))

allRows<-unique(c(tab.subclineventscimt$subclineventscimt_term,tab.clineventswithcimt$clineventswithcimt_term))
                
tabAll<-cbind(
  allRows,
  tab.subclineventscimt[match(allRows,tab.subclineventscimt$subclineventscimt_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithcimt[match(allRows,tab.clineventswithcimt$clineventwithcimt_term),] %>% dplyr::select(!contains("term"))
)

colnames(tabAll)[colnames(tabAll)=="allRows"]<-"predictor"

tabAll.all<-tabAll


# PLWH only

## sub-clinical CIMT events only
tab1.sex<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.gender")
tab1.age<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.smoke") # ridiculous / unstable model coefficients due to no events in one group
tab1.alcohol<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.alcohol") # ridiculous / unstable model coefficients due to no events in one group
tab1.waisthip<-funFitAndSum_modClinEventsCIMTonly.hiv("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsCIMTonly.hiv("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsCIMTonly.hiv("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsCIMTonly.hiv("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsCIMTonly.hiv("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsCIMTonly.hiv("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsCIMTonly.hiv("eGFR_existingCKD") # ridiculous / unstable model coefficients due to no events in one group
#tab1.cmv<-funFitAndSum_modClinEventsCIMTonly.hiv("cmvStatus") # ridiculous / unstable model coefficients due to no events in one group
#tab1.vzv<-funFitAndSum_modClinEventsCIMTonly.hiv("vzvStatus") # ridiculous / unstable model coefficients due to no events in one group
tab1.cmv<-funFitAndSum_modClinEventsCIMTonly.hiv("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsCIMTonly.hiv("vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modClinEventsCIMTonly.hiv("lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modClinEventsCIMTonly.hiv("lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modClinEventsCIMTonly.hiv("log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab1.art<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.artRegimen.2levels")

tab1<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv,
            tab1.cd4base,
            tab1.cd4change,
            tab1.vl,
            tab1.art
)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsCIMTonly.hiv("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)+crf.artRegimen.2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.subclineventscimt<-tabAll


## clinical CVD events + sub-clinical CIMT events
tab1.sex<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.gender")
tab1.age<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.age")
tab1.smoke<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.smoke") # ridiculous / unstable model coefficients due to no events in one group
tab1.alcohol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.alcohol") # ridiculous / unstable model coefficients due to no events in one group
tab1.waisthip<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("physio.waisthip_enrolment")
tab1.bmi<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("physio.bmi_enrolment")
tab1.diabp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("physio.bp_dia_enrolment")
tab1.sysbp<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("physio.bp_sys_enrolment")
tab1.glucose<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("lims.Glucose_enrolment")
tab1.cholesterol<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("lims.Cholesterol_enrolment")
tab1.ckd<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("eGFR_existingCKD") # ridiculous / unstable model coefficients due to no events in one group
#tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("cmvStatus") # ridiculous / unstable model coefficients due to no events in one group
#tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("vzvStatus") # ridiculous / unstable model coefficients due to no events in one group
tab1.cmv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("cmvStatus_2levels")
tab1.vzv<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("vzvStatus_2levels")
tab1.cd4base<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("lims.CD4_Absolute_enrolment")
tab1.cd4change<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("lims.CD4_Absolute_changeFromBaselineAt24Months")
tab1.vl<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab1.art<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.artRegimen.2levels")


tab1<-rbind(tab1.sex,
            tab1.age,
            #tab1.smoke,
            #tab1.alcohol,
            tab1.bmi,
            tab1.diabp,
            tab1.sysbp,
            tab1.glucose,
            tab1.cholesterol,
            #tab1.ckd,
            tab1.cmv,
            tab1.vzv,
            tab1.cd4base,
            tab1.cd4change,
            tab1.vl,
            tab1.art
)
tab1$term<-as.character(tab1$term)

tab2<-funFitAndSum_modClinEventsConfirmedCVDwithCIMT.hiv("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)+crf.artRegimen.2levels")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(c(tab1$term,tab2$term)),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.unadj=NA,rrCI.unadj=NA,pvalue.unadj=NA,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.unadj<-tab1$estimate[match(tabAll$term,tab1$term)]
tabAll$rrCI.unadj<-tab1$rrCI[match(tabAll$term,tab1$term)]
tabAll$pvalue.unadj<-tab1$p.value[match(tabAll$term,tab1$term)]

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithcimt<-tabAll


## combining all in a single table
colnames(tab.subclineventscimt)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt))
colnames(tab.clineventswithcimt)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt))

allRows<-unique(c(tab.subclineventscimt$subclineventscimt_term,tab.clineventswithcimt$clineventswithcimt_term))
                
tabAll<-cbind(
  allRows,
  tab.subclineventscimt[match(allRows,tab.subclineventscimt$subclineventscimt_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithcimt[match(allRows,tab.clineventswithcimt$clineventwithcimt_term),] %>% dplyr::select(!contains("term"))
)

colnames(tab.subclineventscimt.nocd4)<-paste(sep="_","subclineventscimt",colnames(tab.subclineventscimt.nocd4))
colnames(tab.clineventswithcimt.nocd4)<-paste(sep="_","clineventwithcimt",colnames(tab.clineventswithcimt.nocd4))

colnames(tabAll)[colnames(tabAll)=="allRows"]<-"predictor"

tabAll.PLWH.cd4<-tabAll

# Combining PLWH and all participants
rnames<-c("crf.ptypePatient",tabAll.PLWH.cd4[,1])
rn<-c("Participant type: PLWH","Sex: male","Age (years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: persistently high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline at 24 months)","log10 viral load (baseline)","ART: no change to dolutegravir")

colnames(tabAll.PLWH.cd4)<-paste(sep="","PLWHcd4_",colnames(tabAll.PLWH.cd4))
colnames(tabAll.all)<-paste(sep="","all_",colnames(tabAll.all))

tabAll.tab3manu<-cbind(
  rnames,
  tabAll.PLWH.cd4[match(rnames,tabAll.PLWH.cd4[,1]),-c(1,2:4,8:10,14:16,20:22)],
  tabAll.all[match(rnames,tabAll.all[,1]),-c(1,2:4,8:10,14:16,20:22)]
)

tabAll.tab3manu %>%
  dplyr::select(!"rnames") %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("RR","95% CI","p"),4),caption="Model summaries for models fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models) for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.") %>%
  #pack_rows(index = c("Unadjusted models, all data" = 3, "Multiple regression model, all data" = 16, "Multiple regression model, PLWH only" = 18)) %>%
  add_header_above(header=c(" "=1,"Multiple regression model" = 3, "Multiple regression model" = 3,"Multiple regression model" = 3, "Multiple regression model" = 3)) %>%
  add_header_above(header=c(" "=1,"PLWH" = 6,"All participants" = 6)) %>%
  kable_styling(full_width=F)
Table 10.13: Model summaries for models fitted to clinical CVD events and sub-clinical CIMT events (both unadjusted, single variable models and multiple regression models) for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.
PLWH
All participants
Multiple regression model
Multiple regression model
Multiple regression model
Multiple regression model
RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Participant type: PLWH 3.73 ( 1.37,10.16) 0.01 3.63 ( 0.99,13.28) 0.05
Sex: male 0.14 (0.06,0.36) 0.00 0.68 (0.26,1.78) 0.43 0.33 (0.15,0.76) 0.01 0.87 (0.33,2.31) 0.78
Age (years) 1.19 (1.14,1.24) 0.00 1.12 (1.07,1.17) 0.00 1.18 (1.14,1.23) 0.00 1.14 (1.09,1.19) 0.00
BMI 1.04 (0.95,1.15) 0.38 1.05 (0.95,1.16) 0.32 0.96 (0.86,1.07) 0.43 1.03 (0.92,1.16) 0.58
Diastolic blood pressure 1.05 (1.00,1.12) 0.06 1.04 (0.97,1.12) 0.26 1.08 (1.02,1.14) 0.01 1.05 (0.98,1.12) 0.15
Systolic blood pressure 1.00 (0.97,1.03) 0.80 0.99 (0.96,1.03) 0.72 0.97 (0.95,1.00) 0.05 0.99 (0.95,1.02) 0.41
Glucose (baseline) 0.99 (0.83,1.18) 0.91 0.90 (0.62,1.29) 0.56 0.98 (0.80,1.21) 0.85 0.89 (0.62,1.29) 0.54
Cholesterol (baseline) 0.65 (0.45,0.93) 0.02 0.74 (0.48,1.14) 0.17 0.96 (0.71,1.29) 0.77 0.80 (0.54,1.20) 0.29
CMV: persistently high titres 0.92 (0.33,2.54) 0.88 0.68 (0.21,2.23) 0.53 0.87 (0.34,2.23) 0.77 0.72 (0.21,2.47) 0.60
VZV: persistently high titres 12.37 ( 5.68,26.92) 0.00 3.09 (1.16,8.24) 0.03 6.38 ( 3.08,13.23) 0.00 2.97 (1.15,7.67) 0.03
CD4 (baseline) 1.00 (1.00,1.00) 0.18 1.00 (0.99,1.00) 0.11
CD4 (change from baseline at 24 months) 1.00 (1.00,1.00) 0.32 1.00 (1.00,1.00) 0.82
log10 viral load (baseline) 0.75 (0.56,1.01) 0.06 0.96 (0.66,1.38) 0.82
ART: no change to dolutegravir 0.47 (0.22,1.01) 0.05 1.01 (0.43,2.34) 0.98
tabAll.tab3manu$PLWHcd4_subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWHcd4_subclineventscimt_pvalue.adj)))
tabAll.tab3manu$PLWHcd4_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWHcd4_clineventwithcimt_pvalue.adj)))
tabAll.tab3manu$all_subclineventscimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_subclineventscimt_pvalue.adj)))
tabAll.tab3manu$all_clineventwithcimt_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_clineventwithcimt_pvalue.adj)))

write.csv(tabAll.tab3manu,row.names=F,file=paste(sep="_",outPrefix,"CIMT_SubAndClinCVDevents_PLWH_All_TableS7.csv"))

10.2.2.3 PWV

# All participants

## PWV only
tab2<-funFitAndSum_modClinEventsPWVonly("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels",filterPLWH=FALSE)
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(tab2$term),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.subclineventspwv<-tabAll


## clinical events + PWV
tab2<-funFitAndSum_modClinEventsConfirmedCVDwithPWV("crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels",filterPLWH=FALSE)
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(tab2$term),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithpwv<-tabAll


## putting it all together
rm(tabAll)

#colnames(tab.clinevents)<-paste(sep="_","clinevents",colnames(tab.clinevents))
colnames(tab.subclineventspwv)<-paste(sep="_","subclineventspwv",colnames(tab.subclineventspwv))
colnames(tab.clineventswithpwv)<-paste(sep="_","clineventswithpwv",colnames(tab.clineventswithpwv))

allRows<-unique(c(tab.subclineventspwv$subclineventspwv_term,tab.clineventswithpwv$clineventswithpwv_term))

tabAll<-cbind(
  allRows,
  #tab.clinevents[match(allRows,tab.clinevents$clinevents_term),] %>% dplyr::select(!contains("term")),
  tab.subclineventspwv[match(allRows,tab.subclineventspwv$subclineventspwv_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithpwv[match(allRows,tab.clineventswithpwv$clineventswithpwv_term),] %>% dplyr::select(!contains("term"))
)

tabAll.all<-tabAll
rm(tabAll)

# PLWH

## PWV only
tab2<-funFitAndSum_modClinEventsPWVonly("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(tab2$term),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.subclineventspwv<-tabAll


## clinical events + PWV
tab2<-funFitAndSum_modClinEventsConfirmedCVDwithPWV("crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+cmvStatus_2levels+vzvStatus_2levels+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months+log10(lims.HIV_Abbott_Viral_Load_0pt2ml_P_enrolment)")
tab2$term<-as.character(tab2$term)

allRows<-setdiff(unique(tab2$term),"(Intercept)")

tabAll<-data.frame(term=allRows,rr.adj=NA,rrCI.adj=NA,pvalue.adj=NA)

tabAll$rr.adj<-tab2$estimate[match(tabAll$term,tab2$term)]
tabAll$rrCI.adj<-tab2$rrCI[match(tabAll$term,tab2$term)]
tabAll$pvalue.adj<-tab2$p.value[match(tabAll$term,tab2$term)]

tab.clineventswithpwv<-tabAll


## putting it all together
rm(tabAll)

#colnames(tab.clinevents)<-paste(sep="_","clinevents",colnames(tab.clinevents))
colnames(tab.subclineventspwv)<-paste(sep="_","subclineventspwv",colnames(tab.subclineventspwv))
colnames(tab.clineventswithpwv)<-paste(sep="_","clineventswithpwv",colnames(tab.clineventswithpwv))

allRows<-unique(c(tab.subclineventspwv$subclineventspwv_term,tab.clineventswithpwv$clineventswithpwv_term))

tabAll<-cbind(
  allRows,
  #tab.clinevents[match(allRows,tab.clinevents$clinevents_term),] %>% dplyr::select(!contains("term")),
  tab.subclineventspwv[match(allRows,tab.subclineventspwv$subclineventspwv_term),] %>% dplyr::select(!contains("term")),
  tab.clineventswithpwv[match(allRows,tab.clineventswithpwv$clineventswithpwv_term),] %>% dplyr::select(!contains("term"))
)

tabAll.PLWH<-tabAll
rm(tabAll)

# combining for the full table
rnames<-c(tabAll.all[,1],setdiff(tabAll.PLWH[,1],tabAll.all[,1]))
rn<-c("Participant type: PLWH","Sex: male","Age (years)","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","CMV: persistently high titres","VZV: persistently high titres","CD4 (baseline)","CD4 (change from baseline at 24 months)","log viral load (baseline)")

#colnames(tabAll.PLWH.nocd4)<-paste(sep="","PLWHnocd4_",colnames(tabAll.PLWH.nocd4))
colnames(tabAll.PLWH)<-paste(sep="","PLWH_",colnames(tabAll.PLWH))
colnames(tabAll.all)<-paste(sep="","all_",colnames(tabAll.all))

tabAll.tab3manu<-cbind(
  rnames,
  tabAll.PLWH[match(rnames,tabAll.PLWH[,1]),-1],
  tabAll.all[match(rnames,tabAll.all[,1]),-1]
)

tabAll.tab3manu %>%
  dplyr::select(!"rnames") %>%
  kableRn(digits=3,escape=F,row_names=rn,col.names=rep(c("RR","95% CI","p"),5),caption="Model summaries for multiple regression models fitted to clinical CVD events and sub-clinical PWV events for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.") %>%
  add_header_above(header=c(" "=1, "Multiple regression model" = 3, "Multiple regression model" = 3, "Multiple regression model"=3, "Multiple regression model"=3)) %>%
  add_header_above(header=c(" "=1,"PLWH" = 6,"All participants" = 6)) %>%
  kable_styling(full_width=F)
Table 10.14: Model summaries for multiple regression models fitted to clinical CVD events and sub-clinical PWV events for 1) PLWH and 2) all participants. The event count models are quasi-Poisson models and hence report rate ratios. Models fitted to multiply-imputed data.
PLWH
All participants
Multiple regression model
Multiple regression model
Multiple regression model
Multiple regression model
p RR 95% CI p RR 95% CI p RR 95% CI p RR 95% CI p
Participant type: PLWH 0.34 (0.13,0.88) 0.03 0.59 (0.25,1.38) 0.22
Sex: male 1.01 (0.27,3.73) 0.99 1.24 (0.43,3.58) 0.69 1.36 (0.55,3.37) 0.50 1.63 (0.72,3.71) 0.24
Age (years) 1.01 (0.95,1.08) 0.73 1.04 (1.00,1.09) 0.07 1.03 (0.99,1.08) 0.09 1.05 (1.02,1.09) 0.00
BMI 0.91 (0.75,1.11) 0.36 1.00 (0.88,1.13) 0.98 0.94 (0.85,1.03) 0.18 0.98 (0.90,1.07) 0.70
Diastolic blood pressure 1.00 (0.92,1.09) 0.97 1.01 (0.94,1.08) 0.73 1.04 (0.98,1.10) 0.22 1.03 (0.98,1.08) 0.29
Systolic blood pressure 1.03 (0.98,1.08) 0.22 1.01 (0.97,1.05) 0.50 1.00 (0.96,1.03) 0.87 1.00 (0.97,1.03) 0.98
Glucose (baseline) 1.16 (1.07,1.25) 0.00 1.12 (1.04,1.20) 0.00 1.14 (1.07,1.22) 0.00 1.10 (1.03,1.18) 0.00
Cholesterol (baseline) 1.15 (0.66,2.00) 0.62 0.95 (0.61,1.48) 0.83 1.34 (0.93,1.91) 0.11 1.09 (0.79,1.52) 0.59
CMV: persistently high titres 1.37 (0.36,5.17) 0.64 0.91 (0.29,2.85) 0.87 1.22 (0.37,3.99) 0.74 1.04 (0.36,2.98) 0.94
VZV: persistently high titres 1.89 (0.41,8.57) 0.41 1.27 (0.36,4.50) 0.72 1.46 (0.51,4.21) 0.48 1.33 (0.53,3.35) 0.54
CD4 (baseline) 1.00 (1.00,1.01) 0.29 1.00 (1.00,1.00) 0.92
CD4 (change from baseline at 24 months) 1.00 (1.00,1.00) 0.56 1.00 (1.00,1.00) 0.86
log viral load (baseline) 1.41 (0.79,2.51) 0.24 1.40 (0.87,2.24) 0.17
tabAll.tab3manu$PLWH_subclineventspwv_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWH_subclineventspwv_pvalue.adj)))
tabAll.tab3manu$PLWH_clineventswithpwv_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$PLWH_clineventswithpwv_pvalue.adj)))
tabAll.tab3manu$all_subclineventspwv_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_subclineventspwv_pvalue.adj)))
tabAll.tab3manu$all_clineventswithpwv_pvalue.adj<-as.numeric(gsub(pattern="</span>",replacement="",gsub(pattern="<span.*0\\.",replace="0\\.",tabAll.tab3manu$all_clineventswithpwv_pvalue.adj)))

write.csv(tabAll.tab3manu,row.names=F,file=paste(sep="_",outPrefix,"PWV_SubAndClinCVDevents_PLWH_All_TableS5.csv"))

10.3 Time-to-event models

We can visualise clinical CVD events using the Kaplan-Meier estimator, but note that we observed too few events (9 in total) over the study period to make any meaningful analysis. Including sub-clinical CIMT events increases event numbers, but a time-to-event analysis is severely limited by the fact that CIMT sub-clinical events are only known up to a 24-month interval - the entire study period. As such it is more meaningful to consider the event count models given earlier.

if(!is.Date(rhiccaDatWide$lims.sample_date_enrolment)){rhiccaDatWide$lims.sample_date_enrolment<-as_date(mdy_hms(gsub(pattern=":[0-9][0-9][0-9]",replacement="",rhiccaDatWide$lims.sample_date_enrolment)))}
if(!is.Date(rhiccaDatWide$lims.sample_date_6months)){rhiccaDatWide$lims.sample_date_6months<-as_date(mdy_hms(gsub(pattern=":[0-9][0-9][0-9]",replacement="",rhiccaDatWide$lims.sample_date_6months)))}
if(!is.Date(rhiccaDatWide$lims.sample_date_12months)){rhiccaDatWide$lims.sample_date_12months<-as_date(mdy_hms(gsub(pattern=":[0-9][0-9][0-9]",replacement="",rhiccaDatWide$lims.sample_date_12months)))}
if(!is.Date(rhiccaDatWide$lims.sample_date_24months)){rhiccaDatWide$lims.sample_date_24months<-as_date(mdy_hms(gsub(pattern=":[0-9][0-9][0-9]",replacement="",rhiccaDatWide$lims.sample_date_24months)))}

clinEventsKM<-data.frame(
  pid=rhiccaDatWide$pid,
  ptype=rhiccaDatWide$crf.ptype,
  timeStart=NA,
  timeEvent=NA,
  status=0
) %>%
  filter(!is.na(pid))

clinEventsCvdKM<-clinEventsKM
clinEventsCvdWithPwvCimtAbpiKM<-clinEventsKM
clinEventsCvdWithPwvAbpiNoClinKM<-clinEventsKM
clinEventsSystKM<-clinEventsKM
clinEventsInfKM<-clinEventsKM

clinEventsSummary<-clinEventsDat %>%
  group_by(PID) %>%
  dplyr::summarise(
    timeFirstEvent=as.character(min(dmy(data_date),na.rm=T)),
    .groups="drop"
  ) %>%
  filter(!is.na(timeFirstEvent))

clinEventsCvdSummary<-clinEventsDat %>%
  dplyr::filter(category=="CVD") %>%
  group_by(PID) %>%
  dplyr::summarise(
    timeFirstEvent=as.character(min(dmy(data_date),na.rm=T)),
    .groups="drop"
  ) %>%
  filter(!is.na(timeFirstEvent))

clinEventsSystSummary<-clinEventsDat %>%
  dplyr::filter(category=="Systemic disease") %>%
  group_by(PID) %>%
  dplyr::summarise(
    timeFirstEvent=as.character(min(dmy(data_date),na.rm=T)),
    .groups="drop"
  ) %>%
  filter(!is.na(timeFirstEvent))

clinEventsInfSummary<-clinEventsDat %>%
  dplyr::filter(category=="Infection") %>%
  group_by(PID) %>%
  dplyr::summarise(
    timeFirstEvent=as.character(min(dmy(data_date),na.rm=T)),
    .groups="drop"
  ) %>%
  filter(!is.na(timeFirstEvent))

datTmp<-rhiccaDatLong %>%
  dplyr::filter(!is.na(pid)) %>%
  group_by(pid) %>%
  dplyr::summarise(
    maxDate=max(dmy(physio.data_date),na.rm=T),
    .groups="drop"
  )

clinEventsKM$timeStart<-dmy(rhiccaDatWide$crf.data_date[match(clinEventsKM$pid,rhiccaDatWide$pid)])
clinEventsKM$timeEvent<-ymd(clinEventsSummary$timeFirstEvent[match(clinEventsKM$pid,clinEventsSummary$PID)])
clinEventsKM$status[!is.na(as.character(clinEventsKM$timeEvent))]<-1
clinEventsKM$timeEvent[is.na(as.character(clinEventsKM$timeEvent))]<-datTmp$maxDate[match(clinEventsKM$pid[is.na(as.character(clinEventsKM$timeEvent))],datTmp$pid)]

# update start times for retrospectively recruited participants (see email from Laura 10/10/2021)
clinEventsKM$timeStart[clinEventsKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsKM$timeStart[clinEventsKM$pid=="RE1316Q"]<-dmy("20jul2017")

datDeathTmp<-clinEventsDat %>%
  dplyr::filter(DIAGNOSIS=="Death" & data_date!="") %>%
  dplyr::select(PID,data_date)

clinEventsCvdKM$timeStart<-dmy(rhiccaDatWide$crf.data_date[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)])
clinEventsCvdKM$timeEvent<-ymd(clinEventsCvdSummary$timeFirstEvent[match(clinEventsCvdKM$pid,clinEventsCvdSummary$PID)])
clinEventsCvdKM$status[!is.na(as.character(clinEventsCvdKM$timeEvent))]<-1
clinEventsCvdKM$timeEvent[is.na(as.character(clinEventsCvdKM$timeEvent))]<-datTmp$maxDate[match(clinEventsCvdKM$pid[is.na(as.character(clinEventsCvdKM$timeEvent))],datTmp$pid)]
clinEventsCvdKM$timeEvent[clinEventsCvdKM$status==0 & is.element(el=clinEventsCvdKM$pid,set=datDeathTmp$PID)]<-dmy(datDeathTmp$data_date[match(clinEventsCvdKM$pid[clinEventsCvdKM$status==0 & is.element(el=clinEventsCvdKM$pid,set=datDeathTmp$PID)],datDeathTmp$PID)])
clinEventsCvdKM$timeStart[clinEventsCvdKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsCvdKM$timeStart[clinEventsCvdKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsSystKM$timeStart<-dmy(rhiccaDatWide$crf.data_date[match(clinEventsSystKM$pid,rhiccaDatWide$pid)])
clinEventsSystKM$timeEvent<-ymd(clinEventsSystSummary$timeFirstEvent[match(clinEventsSystKM$pid,clinEventsSystSummary$PID)])
clinEventsSystKM$status[!is.na(as.character(clinEventsSystKM$timeEvent))]<-1
clinEventsSystKM$timeEvent[is.na(as.character(clinEventsSystKM$timeEvent))]<-datTmp$maxDate[match(clinEventsSystKM$pid[is.na(as.character(clinEventsSystKM$timeEvent))],datTmp$pid)]
clinEventsSystKM$timeEvent[clinEventsSystKM$status==0 & is.element(el=clinEventsSystKM$pid,set=datDeathTmp$PID)]<-dmy(datDeathTmp$data_date[match(clinEventsSystKM$pid[clinEventsSystKM$status==0 & is.element(el=clinEventsSystKM$pid,set=datDeathTmp$PID)],datDeathTmp$PID)])
clinEventsSystKM$timeStart[clinEventsSystKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsSystKM$timeStart[clinEventsSystKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsInfKM$timeStart<-dmy(rhiccaDatWide$crf.data_date[match(clinEventsInfKM$pid,rhiccaDatWide$pid)])
clinEventsInfKM$timeEvent<-ymd(clinEventsInfSummary$timeFirstEvent[match(clinEventsInfKM$pid,clinEventsInfSummary$PID)])
clinEventsInfKM$status[!is.na(as.character(clinEventsInfKM$timeEvent))]<-1
clinEventsInfKM$timeEvent[is.na(as.character(clinEventsInfKM$timeEvent))]<-datTmp$maxDate[match(clinEventsInfKM$pid[is.na(as.character(clinEventsInfKM$timeEvent))],datTmp$pid)]
clinEventsInfKM$timeEvent[clinEventsInfKM$status==0 & is.element(el=clinEventsInfKM$pid,set=datDeathTmp$PID)]<-dmy(datDeathTmp$data_date[match(clinEventsInfKM$pid[clinEventsInfKM$status==0 & is.element(el=clinEventsInfKM$pid,set=datDeathTmp$PID)],datDeathTmp$PID)])
clinEventsInfKM$timeStart[clinEventsInfKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsInfKM$timeStart[clinEventsInfKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsCvdWithPwvCimtAbpiKM<-clinEventsCvdKM
clinEventsCvdWithPwvCimtKM<-clinEventsCvdKM
clinEventsCvdWithCimtKM<-clinEventsCvdKM
clinEventsCvdWithPwvAbpiKM<-clinEventsCvdKM

clinEventsCvdPwvAbpiOnlyKM<-clinEventsCvdKM
clinEventsCvdPwvAbpiOnlyKM$timeEvent[clinEventsCvdPwvAbpiOnlyKM$status==1]<-datTmp$maxDate[match(clinEventsCvdPwvAbpiOnlyKM$pid[clinEventsCvdPwvAbpiOnlyKM$status==1],datTmp$pid)]
clinEventsCvdPwvAbpiOnlyKM$status<-0
clinEventsCvdPwvAbpiOnlyKM$survTime2<-Inf

clinEventsCvdWithPwvAbpiNoClinKM$timeStart<-dmy(rhiccaDatWide$crf.data_date[match(clinEventsCvdWithPwvAbpiNoClinKM$pid,rhiccaDatWide$pid)])
clinEventsCvdWithPwvAbpiNoClinKM$timeEvent<-datTmp$maxDate[match(clinEventsCvdWithPwvAbpiNoClinKM$pid,datTmp$pid)]

clinEventsNoDerivedKM<-clinEventsKM

# all of these are derived from lab variables only available at enrolment and 24 months...
# 44 additional events
for(pid in as.data.frame(rhiccaDatWide %>% filter(newOnsetDiabetes=="new diabetes" | newOnsetHypercholesterolemia=="new hypercholesterolemia" | newOnsetKidneyCondition=="new kidney condition") %>% dplyr::select(pid))[,1]){
  idx<-which(clinEventsKM$pid==pid)
  if(clinEventsKM$status[idx]==0){
    clinEventsKM$status[idx]<-3
    
    clinEventsKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
    clinEventsKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
  }else if(clinEventsKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsKM$timeStart[idx]) | (!is.na(clinEventsKM$timeStart[idx]) & clinEventsKM$timeStart[idx]>ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]) & (ymd(rhiccaDatWide$lims.sample_date_24months[idx])-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]))<(clinEventsKM$timeEvent[idx]-clinEventsKM$timeStart[idx]))){
      clinEventsKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
      clinEventsKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
    }
  }
}

for(pid in as.data.frame(rhiccaDatWide %>% filter(newOnsetDiabetes=="new diabetes" | newOnsetHypercholesterolemia=="new hypercholesterolemia" | newOnsetKidneyCondition=="new kidney condition") %>% dplyr::select(pid))[,1]){
  idx<-which(clinEventsSystKM$pid==pid)
  if(clinEventsSystKM$status[idx]==0){
    clinEventsSystKM$status[idx]<-3
    
    clinEventsSystKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
    clinEventsSystKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
  }else if(clinEventsSystKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsSystKM$timeStart[idx]) | (!is.na(clinEventsSystKM$timeStart[idx]) & clinEventsSystKM$timeStart[idx]>ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]) & (ymd(rhiccaDatWide$lims.sample_date_24months[idx])-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]))<(clinEventsSystKM$timeEvent[idx]-clinEventsSystKM$timeStart[idx]))){
      clinEventsSystKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
      clinEventsSystKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
    }
  }
}

for(pid in as.data.frame((rhiccaDatWide %>% filter(newOnsetCIMT=="new CIMT vasculopathy") %>% dplyr::select(pid)))[,1]){
  idx<-which(clinEventsCvdWithPwvCimtAbpiKM$pid==pid)
  if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==0){
    clinEventsCvdWithPwvCimtAbpiKM$status[idx]<-3
    
    clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
    clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
  }else if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) | (!is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) & clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]>ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]) & (ymd(rhiccaDatWide$lims.sample_date_24months[idx])-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx]))<(clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]-clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]))){
      clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-ymd(rhiccaDatWide$lims.sample_date_enrolment[idx])
      clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-ymd(rhiccaDatWide$lims.sample_date_24months[idx])
    }
  }
}

clinEventsCvdWithCimtKM<-clinEventsCvdWithPwvCimtAbpiKM

for(pid in as.data.frame((rhiccaDatWide %>% filter(newOnsetPWV=="new PWV vasculopathy") %>% dplyr::select(pid)))[,1]){
  idx<-which(clinEventsCvdWithPwvCimtAbpiKM$pid==pid)
  timePwv<-min(dmy(c(rhiccaDatWide$pwv.data_date_6months[idx][rhiccaDatWide$pwv.pwv_6months[idx]>12],rhiccaDatWide$pwv.data_date_12months[idx][rhiccaDatWide$pwv.pwv_12months[idx]>12],rhiccaDatWide$pwv.data_date_18months[idx][rhiccaDatWide$pwv.pwv_18months[idx]>12],rhiccaDatWide$pwv.data_date_24months[idx][rhiccaDatWide$pwv.pwv_24months[idx]>12],rhiccaDatWide$pwv.data_date_30months[idx][rhiccaDatWide$pwv.pwv_30months[idx]>12])),na.rm=T)
  
  if(length(timePwv)>0){
    timeStart<-dmy(rhiccaDatWide$pwv.data_date_enrolment[idx])
    timeEnd<-timePwv
  }
  
  if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==0){
    clinEventsCvdWithPwvCimtAbpiKM$status[idx]<-3
    clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-timeStart
    clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-timeEnd
  }else if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) | (!is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) & clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]>timeStart & (timeEnd-timeStart)<(clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]-clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]))){
      clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-timeStart
      clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-timeEnd
    }
  }
}

clinEventsCvdWithPwvCimtKM<-clinEventsCvdWithPwvCimtAbpiKM

for(pid in as.data.frame((rhiccaDatWide %>% filter(newOnsetABPI=="new ABPI vasculopathy") %>% dplyr::select(pid)))[,1]){
  idx<-which(clinEventsCvdWithPwvCimtAbpiKM$pid==pid)
  timeAbpi<-min(dmy(c(rhiccaDatWide$abpi.data_date_6months[idx][rhiccaDatWide$abpi.abpi_6months[idx]>0.9],rhiccaDatWide$abpi.data_date_12months[idx][rhiccaDatWide$abpi.abpi_12months[idx]>0.9],rhiccaDatWide$abpi.data_date_18months[idx][rhiccaDatWide$abpi.abpi_18months[idx]>0.9],rhiccaDatWide$abpi.data_date_24months[idx][rhiccaDatWide$abpi.abpi_14months[idx]>0.9],rhiccaDatWide$abpi.data_date_30months[idx][rhiccaDatWide$abpi.abpi_30months[idx]>0.9])),na.rm=T)
  
  if(length(timeAbpi)>0){
    timeStart<-dmy(rhiccaDatWide$abpi.data_date_enrolment[idx])
    timeEnd<-timeAbpi
  }
  
  if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==0){
    clinEventsCvdWithPwvCimtAbpiKM$status[idx]<-3
    clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-timeStart
    clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-timeEnd
  }else if(clinEventsCvdWithPwvCimtAbpiKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) | (!is.na(clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]) & clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]>timeStart & (timeEnd-timeStart)<(clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]-clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]))){
      clinEventsCvdWithPwvCimtAbpiKM$timeStart[idx]<-timeStart
      clinEventsCvdWithPwvCimtAbpiKM$timeEvent[idx]<-timeEnd
    }
  }
}

clinEventsCvdWithPwvCimtAbpiKM$timeStart[clinEventsCvdWithPwvCimtAbpiKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsCvdWithPwvCimtAbpiKM$timeStart[clinEventsCvdWithPwvCimtAbpiKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsCvdWithPwvCimtKM$timeStart[clinEventsCvdWithPwvCimtKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsCvdWithPwvCimtKM$timeStart[clinEventsCvdWithPwvCimtKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsCvdWithCimtKM$timeStart[clinEventsCvdWithCimtKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsCvdWithCimtKM$timeStart[clinEventsCvdWithCimtKM$pid=="RE1316Q"]<-dmy("20jul2017")


for(pid in as.data.frame((rhiccaDatWide %>% filter(newOnsetPWV=="new PWV vasculopathy" | newOnsetABPI=="new ABPI vasculopathy") %>% dplyr::select(pid)))[,1]){
  idx<-which(clinEventsCvdWithPwvAbpiNoClinKM$pid==pid)
  timePwv<-min(dmy(c(rhiccaDatWide$pwv.data_date_6months[idx][rhiccaDatWide$pwv.pwv_6months[idx]>12],rhiccaDatWide$pwv.data_date_12months[idx][rhiccaDatWide$pwv.pwv_12months[idx]>12],rhiccaDatWide$pwv.data_date_18months[idx][rhiccaDatWide$pwv.pwv_18months[idx]>12],rhiccaDatWide$pwv.data_date_24months[idx][rhiccaDatWide$pwv.pwv_24months[idx]>12],rhiccaDatWide$pwv.data_date_30months[idx][rhiccaDatWide$pwv.pwv_30months[idx]>12])),na.rm=T)
  timeAbpi<-min(dmy(c(rhiccaDatWide$abpi.data_date_6months[idx][rhiccaDatWide$abpi.abpi_6months[idx]>0.9],rhiccaDatWide$abpi.data_date_12months[idx][rhiccaDatWide$abpi.abpi_12months[idx]>0.9],rhiccaDatWide$abpi.data_date_18months[idx][rhiccaDatWide$abpi.abpi_18months[idx]>0.9],rhiccaDatWide$abpi.data_date_24months[idx][rhiccaDatWide$abpi.abpi_14months[idx]>0.9],rhiccaDatWide$abpi.data_date_30months[idx][rhiccaDatWide$abpi.abpi_30months[idx]>0.9])),na.rm=T)
  
  if(length(timePwv)>0 & (length(timeAbpi)==0 | (length(timeAbpi)>0) & timePwv<=timeAbpi)){
      timeStart<-dmy(rhiccaDatWide$pwv.data_date_enrolment[idx])
      timeEnd<-timePwv
    }else if(length(timeAbpi)>0 & (length(timePwv)==0 | (length(timePwv)>0) & timeAbpi<=timePwv)){
      timeStart<-dmy(rhiccaDatWide$abpi.data_date_enrolment[idx])
      timeEnd<-timeAbpi
    }
  
  if(clinEventsCvdWithPwvAbpiNoClinKM$status[idx]==0){
    clinEventsCvdWithPwvAbpiNoClinKM$status[idx]<-3
    clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]<-timeStart
    clinEventsCvdWithPwvAbpiNoClinKM$timeEvent[idx]<-timeEnd
  }else if(clinEventsCvdWithPwvAbpiNoClinKM$status[idx]==3){
    # check that either no event is recorded yet OR (that this event occurred earlier AND that it has a shorter interval)
    if(is.na(clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]) | (!is.na(clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]) & clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]>timeStart & (timeEnd-timeStart)<(clinEventsCvdWithPwvAbpiNoClinKM$timeEvent[idx]-clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]))){
      clinEventsCvdWithPwvAbpiNoClinKM$timeStart[idx]<-timeStart
      clinEventsCvdWithPwvAbpiNoClinKM$timeEvent[idx]<-timeEnd
    }
  }
}

clinEventsCvdWithPwvAbpiNoClinKM$timeStart[clinEventsCvdWithPwvAbpiNoClinKM$pid=="RE1097G"]<-dmy("28jun2017")
clinEventsCvdWithPwvAbpiNoClinKM$timeStart[clinEventsCvdWithPwvAbpiNoClinKM$pid=="RE1316Q"]<-dmy("20jul2017")

clinEventsKM<-clinEventsKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsNoDerivedKM<-clinEventsNoDerivedKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdKM<-clinEventsCvdKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdKM.2years<-clinEventsCvdKM
maxTime<-2*365
for(j in 1:nrow(clinEventsCvdKM)){
  if(clinEventsCvdKM.2years$time[j]>maxTime){
    clinEventsCvdKM.2years$time[j]<-maxTime
    if(clinEventsCvdKM.2years$status[j]==0){
      clinEventsCvdKM.2years$survTime1[j]<-maxTime
    }else if(clinEventsCvdKM.2years$status[j]==1){
      clinEventsCvdKM.2years$survTime1[j]<-maxTime
      clinEventsCvdKM.2years$survTime2[j]<-Inf
      clinEventsCvdKM.2years$status[j]<-0
    }
  }
}

clinEventsSystKM<-clinEventsSystKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsInfKM<-clinEventsInfKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdWithPwvCimtAbpiKM<-clinEventsCvdWithPwvCimtAbpiKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdWithPwvCimtKM<-clinEventsCvdWithPwvCimtKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdWithCimtKM<-clinEventsCvdWithCimtKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )

clinEventsCvdWithPwvAbpiNoClinKM<-clinEventsCvdWithPwvAbpiNoClinKM %>%
  mutate(
    timeEnrol=dmy(rhiccaDatWide$crf.data_date)
  ) %>%
  mutate(
    time=timeEvent-timeStart,
    survTime1=case_when(
      status==0~as.numeric(time),
      status==1~as.numeric(time),
      status==3~as.numeric(timeStart-timeEnrol)
    ),
    survTime2=case_when(
      status==0~Inf,
      status==1~as.numeric(time),
      status==3~as.numeric(timeEvent-timeEnrol)
    )
  )


kmMod<-survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsKM)
censMod<-icfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsKM)
censModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsKM)

censModAlt<-ic_np(cbind(survTime1,survTime2)~ptype,data=clinEventsKM) # different package, but otherwise same model as censMod

kmCvdMod<-               survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdKM)
kmCvdMod.2years<-        survfit(Surv(time=survTime1, event=status, type="right") ~ ptype, data = clinEventsCvdKM.2years)
kmCvdWithCimtMod<-       survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithCimtKM)
kmCvdWithPwvCimtMod<-    survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtKM)
kmCvdWithPwvCimtAbpiMod<-survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtAbpiKM)
kmCvdWithPwvAbpiNoClinMod<-survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvAbpiNoClinKM)


censCvdModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdKM)
censCvdModLR.2years<-ictest(Surv(time=survTime1, event=status, type="right") ~ ptype, data = clinEventsCvdKM.2years)
censCvdWithCimtModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithCimtKM)
censCvdWithPwvCimtMod<-icfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtKM)
censCvdWithPwvCimtModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtKM)
censCvdWithPwvCimtAbpiMod<-icfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtAbpiKM)
censCvdWithPwvCimtAbpiModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvCimtAbpiKM)
censCvdWithPwvAbpiNoClinMod<-icfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvAbpiNoClinKM)
censCvdWithPwvAbpiNoClinModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsCvdWithPwvAbpiNoClinKM)

#diag_baseline(censModAFT,dists="weibull")
#diag_covar(censModAFT)

logRankP<-censModLR$p.value
logRankPCvd<-censCvdModLR$p.value
logRankPCvd.2years<-censCvdModLR.2years$p.value
logRankPCvdWithCimt<-censCvdWithCimtModLR$p.value
logRankPCvdWithPwvCimt<-censCvdWithPwvCimtModLR$p.value
logRankPCvdWithPwvCimtAbpi<-censCvdWithPwvCimtAbpiModLR$p.value
logRankPCvdWithPwvAbpiNoClin<-censCvdWithPwvAbpiNoClinModLR$p.value

logRankNoIntCens<-survdiff(Surv(time, status) ~ ptype, data = clinEventsKM %>% filter(status!=3))
logRankPNoIntCens<-1-pchisq(logRankNoIntCens$chisq,df=1)

logRankNoIntCensCvd<-survdiff(Surv(time, status) ~ ptype, data = clinEventsCvdKM %>% filter(status!=3))
logRankPNoIntCensCvd<-1-pchisq(logRankNoIntCensCvd$chisq,df=1)

logRankNoIntCensCvd.2years<-survdiff(Surv(time, status) ~ ptype, data = clinEventsCvdKM.2years %>% filter(status!=3))
logRankPNoIntCensCvd.2years<-1-pchisq(logRankNoIntCensCvd.2years$chisq,df=1)

ggplot2:::autoplot(kmCvdMod) + 
 labs(x = "\n Time to first clinical event (days)", y = "Probability of no event\n", 
 title = "Kaplan-Meier curves for times until first clinical event by participant type.\nEvents include only recorded cardiovascular clinical events.",
 caption = paste(sep="","Log-rank test p-value p = ",format(nsmall=4,round(digits=4,logRankPNoIntCensCvd)))) +
 theme(plot.title = element_text(hjust = 0.5), 
 axis.title.x = element_text(face="bold", colour="#FF7A33", size = 12),
 axis.title.y = element_text(face="bold", colour="#FF7A33", size = 12),
 legend.title = element_text(face="bold", size = 10)) +
  theme(plot.title.position = "plot",plot.title = element_text(hjust = 0))
Kaplan-Meier curves for times until first CVD clinical event by participant type.

Figure 10.2: Kaplan-Meier curves for times until first CVD clinical event by participant type.

ggKM.nolegend<-autoplot(kmCvdMod.2years,) + 
  labs(x = "\n Time to first clinical CVD event (days)", y = "Probability of no event\n") +#, 
       #title = ,
       #caption = paste(sep="","Kaplan-Meier curves for times until first clinical event by participant type.\nEvents include only recorded cardiovascular clinical events.\nLog-rank test p-value p = ",format(nsmall=4,round(digits=4,logRankPNoIntCensCvd.2years)))) +
  theme(plot.title = element_text(hjust = 0.5), 
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        legend.title = element_text(face="bold", size = 10)) +
  theme(plot.title.position = "plot",plot.title = element_text(hjust = 0)) +
  guides(fill="none",color="none") +
  scale_fill_manual(values=c("steelblue","orange"),labels=c("Control","PLWH"),name="") +
  scale_color_manual(values=c("steelblue","orange"),labels=c("Control","PLWH"),name="")

10.4 Multi-panel figure CIMT, PWV and CVD events

grid.arrange(nrow=1,gCIMTAdj.notitle,ggKM.nolegend)

# pdf(width=10,height=5,file=paste(sep="_",outPrefix,"CIMT_CVDevents_Figure2.pdf"))
# grid.arrange(nrow=1,gCIMTAdj.notitle,ggKM.nolegend)
# dev.off()

# grid.arrange(nrow=1,gCIMTAdj.notitle+ggtitle("A. Pre-clinical CVD (CIMT)"),gPWVAdj.notitle+ggtitle("B. Pre-clinical CVD (PWV)"),ggKM.nolegend+ggtitle("C. Clinical CVD events."))
# 
# pdf(width=15,height=6,file=paste(sep="_",outPrefix,"CIMT_PWV_CVDevents_SupFigure1.pdf"))
# grid.arrange(nrow=1,gCIMTAdj.notitle+ggtitle("A. Pre-clinical CVD (CIMT)"),gPWVAdj.notitle+ggtitle("B. Pre-clinical CVD (PWV)"),ggKM.nolegend+ggtitle("C. Clinical CVD events."))
# dev.off()

grid.arrange(nrow=1,gCIMTAdj.notitle+ggtitle("A. Pre-clinical CBD/CVD (CIMT)"),gPWVAdj.notitle+ggtitle("B. Pre-clinical CBD/CVD (PWV)"))

pdf(width=10,height=6,file=paste(sep="_",outPrefix,"CIMT_PWV_CVDevents_SupFigure1.pdf"))
grid.arrange(nrow=1,gCIMTAdj.notitle+ggtitle("A. Pre-clinical CBD/CVD (CIMT)"),gPWVAdj.notitle+ggtitle("B. Pre-clinical CBD/CVD (PWV)"))
dev.off()
## quartz_off_screen 
##                 2

11 Incidence rate of systemic events (mostly hypertension and hypercholesterolaemia) was prevalent in both groups.

From Table 9.1, we see that systemic events are more prevalent in the control group than in the PLWH group (~ double the event rate in controls compared to PLWH). We can drill a bit deeper into this and break down the systemic events into different categories as done in Table 11.1.

clinEventsSystemic<-data.frame(
  pid="PID",
  crf.PLWH="PTYPE",
  type="TYPE"
)

for(j in which(rhiccaDatWide$clinEventCategoryConfirmedSystemicType!="")){
  evts<-unlist(strsplit(split=";",rhiccaDatWide$clinEventCategoryConfirmedSystemicType[j]))
  for(evt in evts){
    clinEventsSystemic<-rbind(clinEventsSystemic,c(rhiccaDatWide$pid[j],as.character(rhiccaDatWide$crf.PLWH[j]),evt))
  }
}
clinEventsSystemic<-clinEventsSystemic[-1,]
clinEventsSystemic$crf.PLWH<-factor(clinEventsSystemic$crf.PLWH,levels=c("PLWH","Control"))
clinEventsSystemic$type[clinEventsSystemic$typ=="chronic renal failure"]<-"kidney disease"

tt<-table(clinEventsSystemic$type,clinEventsSystemic$crf.PLWH)
tt<-data.frame(
  All=tt[,"PLWH"]+tt[,"Control"],
  PLWH=tt[,"PLWH"],
  Control=tt[,"Control"]
)
tt<-rbind(colSums(tt),tt)
rownames(tt)[1]<-"Any"
tt<-tt[c("Any","death","hypercholesterolemia","hypertension","diabetes","kidney disease","anaemia"),]
rownames(tt)<-c("Any","Death","Hypercholesterolemia","Hypertension","Diabetes","Kidney disease","Anaemia")

ttCount<-tt
for(j in 1:ncol(ttCount)){
  if(colnames(tt)[j]!="All"){
    tt[,j]<-tt[,j]/sum(as.numeric(rhiccaDatWide$obsTime[rhiccaDatWide$crf.PLWH==colnames(tt)[j]])/(1000*365.25))
  }else{
    tt[,j]<-tt[,j]/sum(as.numeric(rhiccaDatWide$obsTime)/(1000*365.25))
  }
}

ttCountCount<-ttCount

for(j in 1:ncol(ttCount)){
  for(i in 1:nrow(ttCount)){
    ttCount[i,j]<-paste(sep="",ttCount[i,j]," (",format(nsmall=3,round(digits=3,tt[i,j])),")")
  }
}

ttCount %>%
  kable(escape=F,caption="Listing of systemic disease event types. The numbers in brackets is the rate of events per 1000 person-years.") %>%
  kable_styling(full_width = F)
Table 11.1: Listing of systemic disease event types. The numbers in brackets is the rate of events per 1000 person-years.
All PLWH Control
Any 89 (51.933) 57 (43.736) 32 (77.958)
Death 3 (1.751) 3 (2.302) 0 (0.000)
Hypercholesterolemia 41 (23.924) 25 (19.183) 16 (38.979)
Hypertension 20 (11.670) 11 (8.440) 9 (21.926)
Diabetes 3 (1.751) 1 (0.767) 2 (4.872)
Kidney disease 21 (12.254) 16 (12.277) 5 (12.181)
Anaemia 1 (0.584) 1 (0.767) 0 (0.000)

Looking at an event count model, we get Table 11.2.

modClinEventsConfirmedSystemic<-with(rhiccaDatWide_impMice.clinEventsConfirmed,glm(numClinEventsPerParticipantSystemic~crf.ptype+crf.gender+crf.age+physio.bmi_enrolment+cmvStatus+vzvStatus,offset=obsTime/(1000*365.25),family="quasipoisson"))

summary(pool(modClinEventsConfirmedSystemic)) %>%
  as.data.frame() %>%
  dplyr::select(!term) %>%
  mutate(rownum=1:nrow(summary(pool(modClinEventsConfirmedSystemic)))) %>%
  mutate(estimate=exp(estimate)) %>%
  mutate(p.value=ifelse(rownum>1 & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  dplyr::select(!c(rownum)) %>%
  kableRn(caption="Results for a Poisson regression model for the number of confirmed systemic clinical events per 1,000 person-years, including new onset diabetes and hypercholesterolemia events, with predictors participant type, age, sex, waist-hip ratio, diastolic and systolic blood pressure, glucose and cholesterol (all baseline measurements). Model fitted to multiply imputed data.",digits=4,row_names=c("Intercept","Participant type: PLWH","Sex male","Age (in years)","BMI","CMV: progression to latency","CMV: reactivated latent infection","CMV: persistently high titres","VZV: progression to latency","VZV: reactivated latent infection","VZV: persistently high titres"),escape=F) %>%
  kable_styling(full_width=F)
Table 11.2: Results for a Poisson regression model for the number of confirmed systemic clinical events per 1,000 person-years, including new onset diabetes and hypercholesterolemia events, with predictors participant type, age, sex, waist-hip ratio, diastolic and systolic blood pressure, glucose and cholesterol (all baseline measurements). Model fitted to multiply imputed data.
estimate std.error statistic df p.value
Intercept 0.0582 0.9577 -2.9689 873.2665 0.0031
Participant type: PLWH 0.3980 0.2836 -3.2479 855.7700 0.0012
Sex male 0.5199 0.2445 -2.6751 865.4556 0.0076
Age (in years) 1.0301 0.0116 2.5496 861.5986 0.0110
BMI 0.9950 0.0251 -0.2011 877.9517 0.8407
CMV: progression to latency 1.3793 0.9333 0.3446 143.4293 0.7309
CMV: reactivated latent infection 2.1333 0.3426 2.2112 310.3312 0.0278
CMV: persistently high titres 1.8481 0.3206 1.9157 729.5477 0.0558
VZV: progression to latency 1.1165 0.4104 0.2686 208.5760 0.7885
VZV: reactivated latent infection 1.2362 0.6772 0.3131 223.7142 0.7545
VZV: persistently high titres 1.1780 0.3331 0.4918 278.0674 0.6232

This trend, HIV being protective, holds up in a time-to-event model.

clinEventsKM<-clinEventsKM %>%
  mutate(
    sex=rhiccaDatWide$crf.gender[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    age=rhiccaDatWide$crf.age[match(clinEventsKM$pid,rhiccaDatWide$pid)]-35, # centering on 35 years
    waisthip=rhiccaDatWide$physio.waisthip_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    bmi=rhiccaDatWide$physio.bmi_cat_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    diaBp=rhiccaDatWide$physio.bp_dia_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    sysBp=rhiccaDatWide$physio.bp_sys_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cimtBase=rhiccaDatWide$cimt.cimt_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cimtChange=(rhiccaDatWide$cimt.cimt_24months-rhiccaDatWide$cimt.cimt_enrolment)[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    pwvBase=rhiccaDatWide$pwv.pwv_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    pwvChange=(rhiccaDatWide$pwv.pwv_24months-rhiccaDatWide$pwv.pwv_enrolment)[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    glucose=rhiccaDatWide$lims.Glucose_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cholesterol=rhiccaDatWide$lims.Cholesterol_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
  ) %>%
  mutate(
    waisthipcat=factor(case_when(
      sex=="Female" & waisthip<=0.8 ~ "low",
      sex=="Female" & waisthip>0.8 & waisthip<=0.85 ~ "moderate",
      sex=="Female" & waisthip>0.85 ~ "high",
      sex=="Male" & waisthip<=0.95 ~ "low",
      sex=="Male" & waisthip>0.95 & waisthip<=1 ~ "moderate",
      sex=="Male" & waisthip>1 ~ "high"
    ),levels=c("moderate","low","high"))
  )

clinEventsNoDerivedKM<-clinEventsNoDerivedKM %>%
  mutate(
    sex=rhiccaDatWide$crf.gender[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    age=rhiccaDatWide$crf.age[match(clinEventsKM$pid,rhiccaDatWide$pid)]-35, # centering on 35 years
    waisthip=rhiccaDatWide$physio.waisthip_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    bmi=rhiccaDatWide$physio.bmi_cat_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    diaBp=rhiccaDatWide$physio.bp_dia_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    sysBp=rhiccaDatWide$physio.bp_sys_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cimtBase=rhiccaDatWide$cimt.cimt_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cimtChange=(rhiccaDatWide$cimt.cimt_24months-rhiccaDatWide$cimt.cimt_enrolment)[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    pwvBase=rhiccaDatWide$pwv.pwv_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    pwvChange=(rhiccaDatWide$pwv.pwv_24months-rhiccaDatWide$pwv.pwv_enrolment)[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    glucose=rhiccaDatWide$lims.Glucose_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
    cholesterol=rhiccaDatWide$lims.Cholesterol_enrolment[match(clinEventsKM$pid,rhiccaDatWide$pid)],
  ) %>%
  mutate(
    waisthipcat=factor(case_when(
      sex=="Female" & waisthip<=0.8 ~ "low",
      sex=="Female" & waisthip>0.8 & waisthip<=0.85 ~ "moderate",
      sex=="Female" & waisthip>0.85 ~ "high",
      sex=="Male" & waisthip<=0.95 ~ "low",
      sex=="Male" & waisthip>0.95 & waisthip<=1 ~ "moderate",
      sex=="Male" & waisthip>1 ~ "high"
    ),levels=c("moderate","low","high"))
  )

clinEventsCvdKM<-clinEventsCvdKM %>%
  mutate(
    sex=rhiccaDatWide$crf.gender[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    age=rhiccaDatWide$crf.age[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)]-35, # centering on 35 years
    waisthip=rhiccaDatWide$physio.waisthip_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    bmi=rhiccaDatWide$physio.bmi_cat_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    diaBp=rhiccaDatWide$physio.bp_dia_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    sysBp=rhiccaDatWide$physio.bp_sys_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    cimtBase=rhiccaDatWide$cimt.cimt_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    cimtChange=(rhiccaDatWide$cimt.cimt_24months-rhiccaDatWide$cimt.cimt_enrolment)[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    pwvBase=rhiccaDatWide$pwv.pwv_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    pwvChange=(rhiccaDatWide$pwv.pwv_24months-rhiccaDatWide$pwv.pwv_enrolment)[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    glucose=rhiccaDatWide$lims.Glucose_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
    cholesterol=rhiccaDatWide$lims.Cholesterol_enrolment[match(clinEventsCvdKM$pid,rhiccaDatWide$pid)],
  ) %>%
  mutate(
    waisthipcat=factor(case_when(
      sex=="Female" & waisthip<=0.8 ~ "low",
      sex=="Female" & waisthip>0.8 & waisthip<=0.85 ~ "moderate",
      sex=="Female" & waisthip>0.85 ~ "high",
      sex=="Male" & waisthip<=0.95 ~ "low",
      sex=="Male" & waisthip>0.95 & waisthip<=1 ~ "moderate",
      sex=="Male" & waisthip>1 ~ "high"
    ),levels=c("moderate","low","high"))
  )

clinEventsCvdKM.2years<-clinEventsCvdKM
maxTime<-2*365
for(j in 1:nrow(clinEventsCvdKM)){
  if(clinEventsCvdKM.2years$time[j]>maxTime){
    clinEventsCvdKM.2years$time[j]<-maxTime
    if(clinEventsCvdKM.2years$status[j]==0){
      clinEventsCvdKM.2years$survTime1[j]<-maxTime
    }else if(clinEventsCvdKM.2years$status[j]==1){
      clinEventsCvdKM.2years$survTime1[j]<-maxTime
      clinEventsCvdKM.2years$survTime2[j]<-Inf
      clinEventsCvdKM.2years$status[j]<-0
    }
  }
}

clinEventsSystKM<-clinEventsSystKM %>%
  mutate(
    sex=rhiccaDatWide$crf.gender[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    age=rhiccaDatWide$crf.age[match(clinEventsSystKM$pid,rhiccaDatWide$pid)]-35, # centering on 35 years
    waisthip=rhiccaDatWide$physio.waisthip_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    bmi=rhiccaDatWide$physio.bmi_cat_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    diaBp=rhiccaDatWide$physio.bp_dia_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    sysBp=rhiccaDatWide$physio.bp_sys_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    cimtBase=rhiccaDatWide$cimt.cimt_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    cimtChange=(rhiccaDatWide$cimt.cimt_24months-rhiccaDatWide$cimt.cimt_enrolment)[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    pwvBase=rhiccaDatWide$pwv.pwv_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    pwvChange=(rhiccaDatWide$pwv.pwv_24months-rhiccaDatWide$pwv.pwv_enrolment)[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    glucose=rhiccaDatWide$lims.Glucose_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
    cholesterol=rhiccaDatWide$lims.Cholesterol_enrolment[match(clinEventsSystKM$pid,rhiccaDatWide$pid)],
  ) %>%
  mutate(
    waisthipcat=factor(case_when(
      sex=="Female" & waisthip<=0.8 ~ "low",
      sex=="Female" & waisthip>0.8 & waisthip<=0.85 ~ "moderate",
      sex=="Female" & waisthip>0.85 ~ "high",
      sex=="Male" & waisthip<=0.95 ~ "low",
      sex=="Male" & waisthip>0.95 & waisthip<=1 ~ "moderate",
      sex=="Male" & waisthip>1 ~ "high"
    ),levels=c("moderate","low","high"))
  )

clinEventsInfKM<-clinEventsInfKM %>%
  mutate(
    sex=rhiccaDatWide$crf.gender[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    age=rhiccaDatWide$crf.age[match(clinEventsInfKM$pid,rhiccaDatWide$pid)]-35, # centering on 35 years
    waisthip=rhiccaDatWide$physio.waisthip_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    bmi=rhiccaDatWide$physio.bmi_cat_enrolment[match(clinEventsCvdWithPwvCimtAbpiKM$pid,rhiccaDatWide$pid)],
    diaBp=rhiccaDatWide$physio.bp_dia_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    sysBp=rhiccaDatWide$physio.bp_sys_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    cimtBase=rhiccaDatWide$cimt.cimt_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    cimtChange=(rhiccaDatWide$cimt.cimt_24months-rhiccaDatWide$cimt.cimt_enrolment)[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    pwvBase=rhiccaDatWide$pwv.pwv_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    pwvChange=(rhiccaDatWide$pwv.pwv_24months-rhiccaDatWide$pwv.pwv_enrolment)[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    glucose=rhiccaDatWide$lims.Glucose_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
    cholesterol=rhiccaDatWide$lims.Cholesterol_enrolment[match(clinEventsInfKM$pid,rhiccaDatWide$pid)],
  ) %>%
  mutate(
    waisthipcat=factor(case_when(
      sex=="Female" & waisthip<=0.8 ~ "low",
      sex=="Female" & waisthip>0.8 & waisthip<=0.85 ~ "moderate",
      sex=="Female" & waisthip>0.85 ~ "high",
      sex=="Male" & waisthip<=0.95 ~ "low",
      sex=="Male" & waisthip>0.95 & waisthip<=1 ~ "moderate",
      sex=="Male" & waisthip>1 ~ "high"
    ),levels=c("moderate","low","high"))
  )

censModSystAFT<-ic_par(cbind(survTime1,survTime2)~ptype+sex+age+waisthipcat,data=clinEventsSystKM,model = "aft",dist = "weibull")

summary(censModSystAFT)$summaryParameters %>%
  as.data.frame() %>%
  mutate(rownum=1:nrow(summary(censModSystAFT)$summaryParameters)) %>%
  mutate(p=ifelse(rownum>2 & p<0.05,cell_spec(format(nsmall=4,round(digits=4,p)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p)),bold=F))) %>%
  dplyr::select(!rownum) %>%
  kableRn(row_names = c("log Weibull shape parameter","log Weibull scale parameter","Participant type: PLWH","Sex: male","Age (years)","Waist-hip ratio (low)","Waist-hip ratio (high)"),escape=FALSE,caption="Results from an AFT model for clinical systemic events only.") %>%
  kable_styling(full_width = F)
Table 11.3: Results from an AFT model for clinical systemic events only.
Estimate Exp(Est) Std.Error z-value p
log Weibull shape parameter -0.3979 6.718e-01 0.16920 -2.3510 0.0187
log Weibull scale parameter 10.0400 2.287e+04 0.60340 16.6300 0.0000
Participant type: PLWH 1.1110 3.037e+00 0.38680 2.8720 0.0041
Sex: male 0.8107 2.250e+00 0.45300 1.7900 0.0735
Age (years) -0.0563 9.453e-01 0.01918 -2.9350 0.0033
Waist-hip ratio (low) -0.2816 7.545e-01 0.51790 -0.5438 0.5866
Waist-hip ratio (high) -0.2046 8.149e-01 0.51270 -0.3991 0.6898

Figure 11.1 shows a Kaplan Meier figure to get a feel of when the events are occurring.

kmSystMod<-survfit(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsSystKM)
censSystModLR<-ictest(Surv(time=survTime1, time2=survTime2, type="interval2") ~ ptype, data = clinEventsSystKM)
logRankPCensSyst<-censSystModLR$p.value

ggplot2:::autoplot(kmSystMod) + 
 labs(x = "\n Time to first clinical event (days)", y = "Probability of no event\n", 
 title = "Kaplan-Meier curves for times until first clinical event by participant type.\nEvents include recorded systemic clinical events as well as new onset diabetes, hypercholesterolemia and chronic kidney conditions.\nThe new onset events are only known up to 6-month interval censoring.",
 caption = paste(sep="","Log-rank test p-value p = ",format(nsmall=4,round(digits=4,logRankPCensSyst)))) +
 theme(plot.title = element_text(hjust = 0.5), 
 axis.title.x = element_text(face="bold", colour="#FF7A33", size = 12),
 axis.title.y = element_text(face="bold", colour="#FF7A33", size = 12),
 legend.title = element_text(face="bold", size = 10)) +
  theme(plot.title.position = "plot",plot.title = element_text(hjust = 0))
Kaplan-Meier curves for times until first systemic clinical event or new-onset diabetes, hypercholesterolemia or chronic kidney condition by participant type.

Figure 11.1: Kaplan-Meier curves for times until first systemic clinical event or new-onset diabetes, hypercholesterolemia or chronic kidney condition by participant type.

12 Mediation analysis

Let \(Y\) be a response of interest, \(X\) a predictor and \(M\) a potential mediator variable. \(M\) is said to be a mediator if:

There are direct (not operating through the mediator) and indirect (operating through the mediator) effects of the predictor \(X\) on the outcome \(Y\).

As estimand for a mediation analysis one can focus on controlled direct, natural direct or indirect or stochastic direct or indirect effects (direct and indirect). Each of these will require assumptions: all approaches make consistency and positivity assumptions but differ on assumptions around there being no unmeasured confounding for the various relationships under consideration.

See Rudolph et al. (2018) for more details.

The traditional Baron & Kenny approach to identifying a mediation relationship proceeds as follows:

  1. Regress \(Y\) on \(X\); establish a significant association.
  2. Regress \(M\) on \(X\); establish a significant association.
  3. Regress \(Y\) on both \(X\) and \(M\); establish a significant association between \(Y\) and \(M\) and that the relationship between \(Y\) and \(X\) is now weaker.

There’s further assumptions to be made to be able to interpret this causally and there’s also more sophisticated approaches but they all rely on the same principle: the relationship between \(Y\) and \(X\) is changed if \(M\) is taken into account.

In addition to the 3 variables \(X\), \(Y\) and \(M\), models can be adjusted for other, confounding covariates.

In the case of RHICCA, all of the above is made somewhat more complex by the longitudinal nature of the data. However, the principles of mediation are quite general. What would need to be given care though is whether some effects would be lagged rather than instantaneous.

Here we are interested in exploring the following mediation relationships:

  1. \(Y\) = asymptomatic CVD (continuous CIMT) \(M\) = inflammatory markers (ICAM-1, CD163, IL-6), \(X\) = participant type (HIV)
  2. \(Y\) = asymptomatic CVD (continuous CIMT), \(M\) = herpes virus markers (CMV, VZV), \(X\) = participant type (HIV)
  3. \(Y\) = clinical & sub-clinical CIMT CVD events, \(M\) = inflammatory markers (ICAM-1, CD163, IL-6), \(X\) = participant type (HIV)
  4. \(Y\) = clinical & sub-clinical CIMT CVD events, \(M\) = herpes virus markers (CMV, VZV), \(X\) = participant type (HIV)
  5. Also for systemic events?

The key is to check the 95% confidence interval for the average causal mediation effect (ACME) for each mediation analysis: if this does not include 0, then there is evidence for a mediation.

12.1 Y = asymptomatic CVD (continuous CIMT), M = ICAM-1, X = participant type (HIV)

Our data show an association between X and Y but not X and M and the effect of X on Y does not change when M is included in the model.

This is confirmed by computing and bootstrapping the ACME (and similarly for the natural indirect effect): the 95% confidence interval includes 0, showing no evidence to support a mediation effect.

B<-100
acme<-numeric(B)
estInd<-numeric(B)
tmpLong<-mice::complete(rhiccaDatWide_impMice, action='long', include=TRUE)
nSamp<-unique(table(tmpLong$.imp))
for(b in 1:B){
  idxBoot<-sample(1:nSamp,replace=T,size=nSamp)
  tmpLongBoot<-rbind(tmpLong[tmpLong$.imp==0,][idxBoot,],tmpLong[tmpLong$.imp==1,][idxBoot,])
  for(j in 2:rhiccaDatWide_impMice$m){tmpLongBoot<-rbind(tmpLongBoot,tmpLong[tmpLong$.imp==j,][idxBoot,])}
  rownames(tmpLongBoot)<-NULL
  tmpLongBoot$.id<-rep(1:length(unique(tmpLong$pid)),1+rhiccaDatWide_impMice$m)
  datBoot<-as.mids(tmpLongBoot)
  
  modYX<-summary(pool(with(datBoot,glm(cimtChange~crf.ptype+cimt.cimt_enrolment))))
  modMX<-summary(pool(with(datBoot,glm(lum.ICAM1_change~crf.ptype+lum.ICAM1_enrolment))))
  modYMX<-summary(pool(with(datBoot,glm(cimtChange~crf.ptype+cimt.cimt_enrolment+lum.ICAM1_change))))

  bDirTot<-modYX$estimate[modYX$term=="crf.ptypePatient"]
  bDirMed<-modYMX$estimate[modYMX$term=="crf.ptypePatient"]
  bIndirOut<-modYMX$estimate[modYMX$term=="lum.ICAM1_change"]
  bIndirMed<-modMX$estimate[modMX$term=="crf.ptypePatient"]
  acme[b]<-bDirTot-bDirMed
  estInd[b]<-bIndirOut*bIndirMed
}


modYX<-summary(pool(with(rhiccaDatWide_impMice,glm(cimtChange~crf.ptype+cimt.cimt_enrolment))))
modMX<-summary(pool(with(rhiccaDatWide_impMice,glm(lum.ICAM1_change~crf.ptype+lum.ICAM1_enrolment))))
modYMX<-summary(pool(with(rhiccaDatWide_impMice,glm(cimtChange~crf.ptype+cimt.cimt_enrolment+lum.ICAM1_change))))

bDirTot<-modYX$estimate[modYX$term=="crf.ptypePatient"]
bDirMed<-modYMX$estimate[modYMX$term=="crf.ptypePatient"]

bIndirOut<-modYMX$estimate[modYMX$term=="lum.ICAM1_change"]
bIndirMed<-modMX$estimate[modMX$term=="crf.ptypePatient"]

acmeMainMod<-bDirTot-bDirMed
acmeCI<-quantile(acme,probs=c(0.025,0.975))

indirMainMod<-bIndirOut*bIndirMed
indirCI<-quantile(estInd,probs=c(0.025,0.975))

modOuts<-rbind(modYX,modMX,modYMX)
modOuts %>%
  mutate(
    coefficient=c(c("Intercept","Participant type: PLWH","CIMT (baseline)"),c("Intercept","Participant type: PLWH","ICAM-1 (baseline)"),c("Intercept","Participant type: PLWH","CIMT (baseline)","ICAM-1 (change from baseline)"))
  ) %>%
  dplyr::select(coefficient,estimate,std.error,statistic,df,p.value) %>%
  mutate(p.value=ifelse(coefficient!="Intercept" & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  kableRn(row_names=NULL,row.names=F,escape=F,caption=paste(sep="","Mediation analysis for the effect of participant type through change-from-baseline ICAM-1 on change-from-baseline CIMT. The 95% confidence interval for ACME is given by: (",paste(collapse=", ",format(nsmall=3,round(digits=3,acmeCI))),"). The 95% confidence interval for the natural indirect effect is (",paste(collapse=", ",format(nsmall=3,round(digits=3,indirCI))),").")) %>%
  kable_styling(full_width = FALSE) %>%
  pack_rows(start_row=1,end_row=3,group_label = "model X -> Y") %>%
  pack_rows(start_row=4,end_row=6,group_label = "model X -> M") %>%
  pack_rows(start_row=7,end_row=10,group_label = "model X+M -> Y")
Table 12.1: Mediation analysis for the effect of participant type through change-from-baseline ICAM-1 on change-from-baseline CIMT. The 95% confidence interval for ACME is given by: (0.000, 0.001). The 95% confidence interval for the natural indirect effect is (0.000, 0.001).
coefficient estimate std.error statistic df p.value
model X -> Y
Intercept -9.024600e-03 2.355110e-02 -0.3831938 66.37258 0.7028
Participant type: PLWH 1.635400e-02 6.815900e-03 2.3994041 517.78110 0.0168
CIMT (baseline) 5.118220e-02 4.355430e-02 1.1751343 59.17108 0.2446
model X -> M
Intercept 9.104056e+04 1.455526e+04 6.2548215 70.95405 0.0000
Participant type: PLWH -2.138729e+04 1.330448e+04 -1.6075254 372.65028 0.1088
ICAM-1 (baseline) -8.891879e-01 7.042010e-02 -12.6269019 14.83445 0.0000
model X+M -> Y
Intercept -9.136300e-03 2.353740e-02 -0.3881606 66.88558 0.6991
Participant type: PLWH 1.618370e-02 6.855100e-03 2.3608388 479.80435 0.0186
CIMT (baseline) 5.126270e-02 4.354920e-02 1.1771211 59.38764 0.2438
ICAM-1 (change from baseline) 0.000000e+00 0.000000e+00 -0.4589472 397.33778 0.6465

12.2 Y = asymptomatic CVD (continuous CIMT), M = ICAM-1, CD163, IL-6, X = VZV status (PLWH only)

Our data show an association between X and Y but not X and any of the M variables and the effect of X on Y does not change when the M variables are included in the model.

This is confirmed by computing and bootstrapping the ACME (and similarly for the natural indirect effects): the 95% confidence interval includes 0, showing no evidence to support a mediation effect.

B<-100
acme<-numeric(B)
estInd1<-numeric(B)
estInd2<-numeric(B)
estInd3<-numeric(B)
tmpLong<-mice::complete(rhiccaDatWide_impMice.hiv, action='long', include=TRUE)
nSamp<-unique(table(tmpLong$.imp))
for(b in 1:B){
  idxBoot<-sample(1:nSamp,replace=T,size=nSamp)
  tmpLongBoot<-rbind(tmpLong[tmpLong$.imp==0,][idxBoot,],tmpLong[tmpLong$.imp==1,][idxBoot,])
  for(j in 2:rhiccaDatWide_impMice.hiv$m){tmpLongBoot<-rbind(tmpLongBoot,tmpLong[tmpLong$.imp==j,][idxBoot,])}
  rownames(tmpLongBoot)<-NULL
  tmpLongBoot$.id<-rep(1:length(unique(tmpLong$pid)),1+rhiccaDatWide_impMice.hiv$m)
  datBoot<-as.mids(tmpLongBoot)
  
  modYX<-summary(pool(with(datBoot,glm(cimtChange~vzvStatus+cimt.cimt_enrolment))))
  modM1X<-summary(pool(with(datBoot,glm(log(lum.ICAM1_enrolment)~vzvStatus))))
  modM2X<-summary(pool(with(datBoot,glm(log(lum.CD163_enrolment)~vzvStatus))))
  modM3X<-summary(pool(with(datBoot,glm(log(lum.IL6_enrolment)~vzvStatus))))
  modYMX<-summary(pool(with(datBoot,glm(cimtChange~vzvStatus+cimt.cimt_enrolment+log(lum.ICAM1_enrolment)+log(lum.CD163_enrolment)+log(lum.IL6_enrolment)))))

  bDirTot<-modYX$estimate[modYX$term=="vzvStatuspersistently high titres"]
  bDirMed<-modYMX$estimate[modYMX$term=="vzvStatuspersistently high titres"]
  bIndir1Out<-modYMX$estimate[modYMX$term=="log(lum.ICAM1_enrolment)"]
  bIndir1Med<-modM1X$estimate[modM1X$term=="vzvStatuspersistently high titres"]
  bIndir2Out<-modYMX$estimate[modYMX$term=="log(lum.CD163_enrolment)"]
  bIndir2Med<-modM2X$estimate[modM2X$term=="vzvStatuspersistently high titres"]
  bIndir3Out<-modYMX$estimate[modYMX$term=="log(lum.IL6_enrolment)"]
  bIndir3Med<-modM3X$estimate[modM3X$term=="vzvStatuspersistently high titres"]
  acme[b]<-bDirTot-bDirMed
  estInd1[b]<-bIndir1Out*bIndir1Med
  estInd2[b]<-bIndir2Out*bIndir2Med
  estInd3[b]<-bIndir3Out*bIndir3Med
}

modYX<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(cimtChange~vzvStatus+cimt.cimt_enrolment))))
modM1X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.ICAM1_enrolment)~vzvStatus))))
modM2X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.CD163_enrolment)~vzvStatus))))
modM3X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.IL6_enrolment)~vzvStatus))))
modYMX<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(cimtChange~vzvStatus+cimt.cimt_enrolment+log(lum.ICAM1_enrolment)+log(lum.CD163_enrolment)+log(lum.IL6_enrolment)))))

bDirTot<-modYX$estimate[modYX$term=="vzvStatuspersistently high titres"]
bDirMed<-modYMX$estimate[modYMX$term=="vzvStatuspersistently high titres"]
bIndir1Out<-modYMX$estimate[modYMX$term=="log(lum.ICAM1_enrolment)"]
bIndir1Med<-modM1X$estimate[modM1X$term=="vzvStatuspersistently high titres"]
bIndir2Out<-modYMX$estimate[modYMX$term=="log(lum.CD163_enrolment)"]
bIndir2Med<-modM2X$estimate[modM2X$term=="vzvStatuspersistently high titres"]
bIndir3Out<-modYMX$estimate[modYMX$term=="log(lum.IL6_enrolment)"]
bIndir3Med<-modM3X$estimate[modM3X$term=="vzvStatuspersistently high titres"]

acmeMainMod<-bDirTot-bDirMed
acmeCI<-quantile(acme,probs=c(0.025,0.975))

indir1MainMod<-bIndir1Out*bIndir1Med
indir2MainMod<-bIndir2Out*bIndir2Med
indir3MainMod<-bIndir3Out*bIndir3Med
indir1CI<-quantile(estInd1,probs=c(0.025,0.975))
indir2CI<-quantile(estInd2,probs=c(0.025,0.975))
indir3CI<-quantile(estInd3,probs=c(0.025,0.975))

modOuts<-rbind(modYX,modM1X,modM2X,modM3X,modYMX)
modOuts %>%
  mutate(
    coefficient=c(c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CIMT (baseline)"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CIMT (baseline)","log ICAM-1 (baseline)","log CD163 (baseline)","log IL-6 (baseline)"))
  ) %>%
  dplyr::select(coefficient,estimate,std.error,statistic,df,p.value) %>%
  mutate(p.value=ifelse(coefficient!="Intercept" & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  kableRn(row_names=NULL,row.names=F,escape=F,caption=paste(sep="","Mediation analysis for the effect of VZV status through baseline inflammatory markers on change-from-baseline CIMT (PLWH only). The 95% confidence interval for ACME is given by: (",paste(collapse=", ",format(nsmall=3,round(digits=3,acmeCI))),"). The 95% CI for the 3 natural indirect effects of ICAM-1, CD163 and IL-6 are given by (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir1CI))),"), (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir2CI))),") and (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir3CI))),").")) %>%
  kable_styling(full_width = FALSE) %>%
  pack_rows(start_row=1,end_row=5,group_label = "model X -> Y") %>%
  pack_rows(start_row=6,end_row=9,group_label = "model X -> M (ICAM-1)") %>%
  pack_rows(start_row=10,end_row=13,group_label = "model X -> M (CD163)") %>%
  pack_rows(start_row=14,end_row=17,group_label = "model X -> M (IL-6)") %>%
  pack_rows(start_row=18,end_row=25,group_label = "model X+M -> Y")
Table 12.2: Mediation analysis for the effect of VZV status through baseline inflammatory markers on change-from-baseline CIMT (PLWH only). The 95% confidence interval for ACME is given by: (-0.001, 0.002). The 95% CI for the 3 natural indirect effects of ICAM-1, CD163 and IL-6 are given by (-0.001, 0.001), (-0.002, 0.001) and (0.000, 0.001).
coefficient estimate std.error statistic df p.value
model X -> Y
Intercept -0.0221326 0.0267480 -0.8274500 91.30846 0.4101
VZV: progression to latency 0.0221606 0.0116774 1.8977320 97.98794 0.0607
VZV: reactivation 0.0039354 0.0155883 0.2524579 309.93213 0.8009
VZV: persistently high titres 0.0197700 0.0091696 2.1560401 289.06696 0.0319
CIMT (baseline) 0.0966808 0.0541096 1.7867582 69.43050 0.0783
model X -> M (ICAM-1)
Intercept 11.1967995 0.0520230 215.2278245 413.75236 0.0000
VZV: progression to latency -0.0345259 0.1362411 -0.2534176 206.89368 0.8002
VZV: reactivation 0.0441548 0.2257248 0.1956135 65.68688 0.8455
VZV: persistently high titres 0.0533616 0.1194097 0.4468784 156.94341 0.6556
model X -> M (CD163)
Intercept 4.4709358 0.0462295 96.7117535 354.79926 0.0000
VZV: progression to latency 0.0466885 0.1248151 0.3740614 126.72971 0.7090
VZV: reactivation -0.1279141 0.2018560 -0.6336896 58.95432 0.5287
VZV: persistently high titres 0.0497791 0.1223808 0.4067557 47.07838 0.6860
model X -> M (IL-6)
Intercept 0.8163182 0.0770376 10.5963555 67.35016 0.0000
VZV: progression to latency 0.1333728 0.1923942 0.6932266 68.02669 0.4905
VZV: reactivation 0.3610922 0.2645358 1.3650030 121.23102 0.1748
VZV: persistently high titres 0.1503503 0.1634218 0.9200132 73.03403 0.3606
model X+M -> Y
Intercept -0.0311183 0.0445378 -0.6986942 242.13010 0.4854
VZV: progression to latency 0.0220470 0.0116913 1.8857573 98.10594 0.0623
VZV: reactivation 0.0022971 0.0156642 0.1466455 303.89534 0.8835
VZV: persistently high titres 0.0194567 0.0091606 2.1239597 302.26393 0.0345
CIMT (baseline) 0.0992796 0.0539547 1.8400555 71.94369 0.0699
log ICAM-1 (baseline) 0.0020192 0.0039793 0.5074215 90.02038 0.6131
log CD163 (baseline) -0.0038604 0.0040030 -0.9643800 474.20978 0.3353
log IL-6 (baseline) 0.0028465 0.0027225 1.0455485 155.29901 0.2974
tmp<-modOuts %>%
  mutate(
    coefficient=c(c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CIMT (baseline)"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","CIMT (baseline)","log ICAM-1 (baseline)","log CD163 (baseline)","log IL-6 (baseline)"))
  ) %>%
  dplyr::select(coefficient,estimate,std.error,statistic,df,p.value) 

write.csv(tmp,file=paste(sep="_",outPrefix,"Mediation_YcimtMinflammatoryXvzv_Table4a.csv"))

12.3 Y = clinical and subclinical (CIMT) CVD events, M = ICAM-1, CD163, IL-6, X = VZV status (PLWH only)

Our data show an association between X and Y but not X and any of the M variables and the effect of X on Y does not change when the M variables are included in the model.

This is confirmed by computing and bootstrapping the ACME (and similarly for the natural indirect effects): the 95% confidence interval includes 0, showing no evidence to support a mediation effect.

B<-100
acme<-numeric(B)
estInd1<-numeric(B)
estInd2<-numeric(B)
estInd3<-numeric(B)
tmpLong<-mice::complete(rhiccaDatWide_impMice.hiv, action='long', include=TRUE)
tmpLong2<-mice::complete(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"), action='long', include=TRUE)
nSamp<-unique(table(tmpLong$.imp))
m<-rhiccaDatWide_impMice.hiv$m
nSamp2<-unique(table(tmpLong2$.imp))
m2<-rhiccaDatWide_impMice.clinEventsConfirmed$m
if(nSamp!=nSamp2){stop("nSamp and nSamp2 should be the same!")}
if(m!=m2){stop("m and m2 should be the same!")}
for(b in 1:B){
  idxBoot<-sample(1:nSamp,replace=T,size=nSamp)
  tmpLongBoot<-rbind(tmpLong[tmpLong$.imp==0,][idxBoot,],tmpLong[tmpLong$.imp==1,][idxBoot,])
  tmpLong2Boot<-rbind(tmpLong2[tmpLong2$.imp==0,][idxBoot,],tmpLong2[tmpLong2$.imp==1,][idxBoot,])
  for(j in 2:m){
    tmpLongBoot<-rbind(tmpLongBoot,tmpLong[tmpLong$.imp==j,][idxBoot,])
    tmpLong2Boot<-rbind(tmpLong2Boot,tmpLong2[tmpLong2$.imp==j,][idxBoot,])
  }
  rownames(tmpLongBoot)<-NULL
  rownames(tmpLong2Boot)<-NULL
  tmpLongBoot$.id<-rep(1:length(unique(tmpLong$pid)),1+m)
  tmpLong2Boot$.id<-rep(1:length(unique(tmpLong2$pid)),1+m)
  datBoot<-as.mids(tmpLongBoot)
  datBoot2<-as.mids(tmpLong2Boot)
  
  modYX<-summary(pool(with(datBoot2,glm(numClinEventsPerParticipantCVDwithCIMT~crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+vzvStatus,offset=obsTime/(1000*365.25),family="quasipoisson"))))
  modM1X<-summary(pool(with(datBoot,glm(log(lum.ICAM1_enrolment)~vzvStatus))))
  modM2X<-summary(pool(with(datBoot,glm(log(lum.CD163_enrolment)~vzvStatus))))
  modM3X<-summary(pool(with(datBoot,glm(log(lum.IL6_enrolment)~vzvStatus))))
  modYMX<-summary(pool(with(datBoot2,glm(numClinEventsPerParticipantCVDwithCIMT~crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+vzvStatus+log(lum.ICAM1_enrolment)+log(lum.CD163_enrolment)+log(lum.IL6_enrolment),offset=obsTime/(1000*365.25),family="quasipoisson"))))

  bDirTot<-modYX$estimate[modYX$term=="vzvStatuspersistently high titres"]
  bDirMed<-modYMX$estimate[modYMX$term=="vzvStatuspersistently high titres"]
  bIndir1Out<-modYMX$estimate[modYMX$term=="log(lum.ICAM1_enrolment)"]
  bIndir1Med<-modM1X$estimate[modM1X$term=="vzvStatuspersistently high titres"]
  bIndir2Out<-modYMX$estimate[modYMX$term=="log(lum.CD163_enrolment)"]
  bIndir2Med<-modM2X$estimate[modM2X$term=="vzvStatuspersistently high titres"]
  bIndir3Out<-modYMX$estimate[modYMX$term=="log(lum.IL6_enrolment)"]
  bIndir3Med<-modM3X$estimate[modM3X$term=="vzvStatuspersistently high titres"]
  acme[b]<-bDirTot-bDirMed
  estInd1[b]<-bIndir1Out*bIndir1Med
  estInd2[b]<-bIndir2Out*bIndir2Med
  estInd3[b]<-bIndir3Out*bIndir3Med
}

modYX<-summary(pool(with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVDwithCIMT~crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+vzvStatus,offset=obsTime/(1000*365.25),family="quasipoisson"))))
modM1X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.ICAM1_enrolment)~vzvStatus))))
modM2X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.CD163_enrolment)~vzvStatus))))
modM3X<-summary(pool(with(rhiccaDatWide_impMice.hiv,glm(log(lum.IL6_enrolment)~vzvStatus))))
modYMX<-summary(pool(with(rhiccaDatWide_impMice.clinEventsConfirmed %>% dplyr::filter(crf.ptype=="Patient"),glm(numClinEventsPerParticipantCVDwithCIMT~crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+vzvStatus+log(lum.ICAM1_enrolment)+log(lum.CD163_enrolment)+log(lum.IL6_enrolment),offset=obsTime/(1000*365.25),family="quasipoisson"))))

bDirTot<-modYX$estimate[modYX$term=="vzvStatuspersistently high titres"]
bDirMed<-modYMX$estimate[modYMX$term=="vzvStatuspersistently high titres"]
bIndir1Out<-modYMX$estimate[modYMX$term=="log(lum.ICAM1_enrolment)"]
bIndir1Med<-modM1X$estimate[modM1X$term=="vzvStatuspersistently high titres"]
bIndir2Out<-modYMX$estimate[modYMX$term=="log(lum.CD163_enrolment)"]
bIndir2Med<-modM2X$estimate[modM2X$term=="vzvStatuspersistently high titres"]
bIndir3Out<-modYMX$estimate[modYMX$term=="log(lum.IL6_enrolment)"]
bIndir3Med<-modM3X$estimate[modM3X$term=="vzvStatuspersistently high titres"]

acmeMainMod<-bDirTot-bDirMed
acmeCI<-quantile(acme,probs=c(0.025,0.975))

indir1MainMod<-bIndir1Out*bIndir1Med
indir2MainMod<-bIndir2Out*bIndir2Med
indir3MainMod<-bIndir3Out*bIndir3Med
indir1CI<-quantile(estInd1,probs=c(0.025,0.975))
indir2CI<-quantile(estInd2,probs=c(0.025,0.975))
indir3CI<-quantile(estInd3,probs=c(0.025,0.975))

modOuts<-rbind(modYX,modM1X,modM2X,modM3X,modYMX)
modOuts %>%
  mutate(
    coefficient=c(c("Intercept","Sex male","Age","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),rep(c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),3),c("Intercept","Sex male","Age","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","log ICAM-1 (baseline)","log CD163 (baseline)","log IL-6 (baseline)"))
  ) %>%
  dplyr::select(coefficient,estimate,std.error,statistic,df,p.value) %>%
  mutate(p.value=ifelse(coefficient!="Intercept" & p.value<0.05,cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=T),cell_spec(format(nsmall=4,round(digits=4,p.value)),bold=F))) %>%
  kableRn(row_names=NULL,row.names=F,escape=F,caption=paste(sep="","Mediation analysis for the effect of VZV status through baseline inflammatory markers on clinical and sub-clinical (CIMT) CVD events. The 95% confidence interval for ACME is given by: (",paste(collapse=", ",format(nsmall=3,round(digits=3,acmeCI))),"). The 95% CI for the 3 natural indirect effects of ICAM-1, CD163 and IL-6 are given by (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir1CI))),"), (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir2CI))),") and (",paste(collapse=", ",format(nsmall=3,round(digits=3,indir3CI))),").")) %>%
  kable_styling(full_width = FALSE) %>%
  pack_rows(start_row=1,end_row=11,group_label = "model X -> Y") %>%
  pack_rows(start_row=12,end_row=15,group_label = "model X -> M (ICAM-1)") %>%
  pack_rows(start_row=16,end_row=19,group_label = "model X -> M (CD163)") %>%
  pack_rows(start_row=20,end_row=23,group_label = "model X -> M (IL-6)") %>%
  pack_rows(start_row=24,end_row=37,group_label = "model X+M -> Y")
Table 12.3: Mediation analysis for the effect of VZV status through baseline inflammatory markers on clinical and sub-clinical (CIMT) CVD events. The 95% confidence interval for ACME is given by: (-0.210, 0.435). The 95% CI for the 3 natural indirect effects of ICAM-1, CD163 and IL-6 are given by (-0.055, 0.102), (-0.045, 0.074) and (-0.063, 0.042).
coefficient estimate std.error statistic df p.value
model X -> Y
Intercept -10.8361176 2.2942172 -4.7232309 652.33354 0.0000
Sex male -0.4261672 0.5070599 -0.8404671 690.22605 0.4009
Age 0.1157578 0.0233150 4.9649552 654.44567 0.0000
BMI 0.0540901 0.0538911 1.0036927 669.77182 0.3159
Diastolic blood pressure 0.0278238 0.0361471 0.7697379 692.17931 0.4417
Systolic blood pressure -0.0044602 0.0202929 -0.2197901 692.04773 0.8261
Glucose (baseline) -0.0804439 0.1671041 -0.4814003 684.83751 0.6304
Cholesterol (baseline) -0.2849331 0.2129771 -1.3378578 685.05892 0.1814
VZV: progression to latency -0.2869483 0.9519995 -0.3014164 210.55641 0.7634
VZV: reactivation -6.6334879 865.4982673 -0.0076644 696.93804 0.9939
VZV: persistently high titres 1.1685419 0.4985307 2.3439719 323.39877 0.0197
model X -> M (ICAM-1)
Intercept 11.1967995 0.0520230 215.2278245 413.75236 0.0000
VZV: progression to latency -0.0345259 0.1362411 -0.2534176 206.89368 0.8002
VZV: reactivation 0.0441548 0.2257248 0.1956135 65.68688 0.8455
VZV: persistently high titres 0.0533616 0.1194097 0.4468784 156.94341 0.6556
model X -> M (CD163)
Intercept 4.4709358 0.0462295 96.7117535 354.79926 0.0000
VZV: progression to latency 0.0466885 0.1248151 0.3740614 126.72971 0.7090
VZV: reactivation -0.1279141 0.2018560 -0.6336896 58.95432 0.5287
VZV: persistently high titres 0.0497791 0.1223808 0.4067557 47.07838 0.6860
model X -> M (IL-6)
Intercept 0.8163182 0.0770376 10.5963555 67.35016 0.0000
VZV: progression to latency 0.1333728 0.1923942 0.6932266 68.02669 0.4905
VZV: reactivation 0.3610922 0.2645358 1.3650030 121.23102 0.1748
VZV: persistently high titres 0.1503503 0.1634218 0.9200132 73.03403 0.3606
model X+M -> Y
Intercept -13.6067377 3.4447663 -3.9499741 380.06411 0.0001
Sex male -0.4136555 0.4995888 -0.8279919 681.22151 0.4080
Age 0.1187297 0.0243020 4.8855852 609.88485 0.0000
BMI 0.0554191 0.0542189 1.0221360 632.66430 0.3071
Diastolic blood pressure 0.0143531 0.0376271 0.3814568 688.65581 0.7030
Systolic blood pressure 0.0040485 0.0216251 0.1872148 677.99552 0.8515
Glucose (baseline) -0.0658565 0.1506520 -0.4371436 658.27419 0.6622
Cholesterol (baseline) -0.2348602 0.2273020 -1.0332521 621.13520 0.3019
VZV: progression to latency -0.4535073 0.9580223 -0.4733786 197.77731 0.6365
VZV: reactivation -6.7528177 849.9980090 -0.0079445 693.93714 0.9937
VZV: persistently high titres 0.9797346 0.5145522 1.9040527 334.33662 0.0578
log ICAM-1 (baseline) 0.1319484 0.2406412 0.5483201 176.76827 0.5842
log CD163 (baseline) 0.2075722 0.2317415 0.8957059 320.28122 0.3711
log IL-6 (baseline) -0.0133401 0.1976327 -0.0674997 87.70231 0.9463
tmp<-modOuts %>%
  mutate(
    coefficient=c(c("Intercept","Sex male","Age","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),rep(c("Intercept","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres"),3),c("Intercept","Sex male","Age","BMI","Diastolic blood pressure","Systolic blood pressure","Glucose (baseline)","Cholesterol (baseline)","VZV: progression to latency","VZV: reactivation","VZV: persistently high titres","log ICAM-1 (baseline)","log CD163 (baseline)","log IL-6 (baseline)"))
  ) %>%
  dplyr::select(coefficient,estimate,std.error,statistic,df,p.value)

write.csv(tmp,file=paste(sep="_",outPrefix,"Mediation_YeventsMinflammatoryXvzv_Table4b.csv"))

13 Additional things for discussion

rhiccaDatWide <- rhiccaDatWide %>%
  dplyr::mutate(
    cimt.cimt_changeFromBaseline=cimt.cimt_24months-cimt.cimt_enrolment,
    cimt.cimt_changeFromBaselineRelative=(cimt.cimt_24months-cimt.cimt_enrolment)/cimt.cimt_enrolment
  )

cimtRelChangeSummary <- rhiccaDatWide %>%
  dplyr::filter(!is.na(crf.PLWH) & !is.na(vzvStatus_2levels)) %>%
  dplyr::group_by(crf.PLWH,vzvStatus_2levels) %>%
  dplyr::summarise(
    minCimtRelChange=paste(sep="",format(nsmall=1,round(digits=1,100*min(cimt.cimt_changeFromBaselineRelative,na.rm=TRUE))),"%"),
    maxCimtRelChange=paste(sep="",format(nsmall=1,round(digits=1,100*max(cimt.cimt_changeFromBaselineRelative,na.rm=TRUE))),"%"),
    median=paste(sep="",format(nsmall=1,round(digits=1,100*quantile(probs=0.5,cimt.cimt_changeFromBaselineRelative,na.rm=TRUE))),"%"),
    q25CimtRelChange=paste(sep="",format(nsmall=1,round(digits=1,100*quantile(probs=0.25,cimt.cimt_changeFromBaselineRelative,na.rm=TRUE))),"%"),
    q75CimtRelChange=paste(sep="",format(nsmall=1,round(digits=1,100*quantile(probs=0.75,cimt.cimt_changeFromBaselineRelative,na.rm=TRUE))),"%")
  )

cimtRelChangeSummary %>%
  kable(row.names=F,col.names=c("Participant type","VZV status","Minimum","Maximum","Median","25th percentile","75th percentile")) %>%
  kable_styling(full_width = FALSE) %>%
  add_header_above(header=c(" "=2,"Relative change in CIMT from enrolment to 24 months"=5))
Relative change in CIMT from enrolment to 24 months
Participant type VZV status Minimum Maximum Median 25th percentile 75th percentile
Control not persistently high titres -10.1% 23.3% 3.5% -1.3% 8.9%
Control persistently high titres -14.9% 13.9% 0.5% -1.6% 2.6%
PLWH not persistently high titres -15.7% 198.7% 4.7% 0.4% 10.3%
PLWH persistently high titres -17.6% 206.1% 7.1% 4.1% 11.9%
tmp<-complete(rhiccaDatWide_impMice,action = "long",include=TRUE)
tmp<-tmp %>% mutate(cimtChange=cimt.cimt_24months-cimt.cimt_enrolment)
tmp.mids<-as.mids(tmp)

tt<-with(tmp.mids %>% filter(crf.ptype=="Patient"),lm(cimtChange~1))
ttChange<-summary(pool(tt))$estimate
tt<-with(tmp.mids %>% filter(crf.ptype=="Patient"),lm(cimt.cimt_enrolment~1))
ttBaseline<-summary(pool(tt))$estimate
cat(paste(sep="","Proportion change in CIMT from baseline to 24 months in PLWH: ",ttChange/ttBaseline,"\n"))
## Proportion change in CIMT from baseline to 24 months in PLWH: 0.0656813550256049
tt<-with(tmp.mids %>% filter(crf.ptype=="Control"),lm(cimtChange~1))
ttChange<-summary(pool(tt))$estimate
tt<-with(tmp.mids %>% filter(crf.ptype=="Control"),lm(cimt.cimt_enrolment~1))
ttBaseline<-summary(pool(tt))$estimate
cat(paste(sep="","Proportion change in CIMT from baseline to 24 months in Controls: ",ttChange/ttBaseline,"\n"))
## Proportion change in CIMT from baseline to 24 months in Controls: 0.0339636189564385
tt<-with(tmp.mids,lm(cimtChange~crf.ptype)); summary(pool(tt))
##               term   estimate   std.error statistic       df     p.value
## 1      (Intercept) 0.01780108 0.005892811  3.020812 784.5559 0.002602819
## 2 crf.ptypePatient 0.01540503 0.006711295  2.295388 636.4445 0.022035231
fisher.test(table(rhiccaDatWide$crf.artRegimen.2levels,rhiccaDatWide$cmvStatus_2levels))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(rhiccaDatWide$crf.artRegimen.2levels, rhiccaDatWide$cmvStatus_2levels)
## p-value = 0.006234
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  1.192250 3.240689
## sample estimates:
## odds ratio 
##   1.957222
fisher.test(table(rhiccaDatWide$crf.artRegimen.2levels,rhiccaDatWide$vzvStatus_2levels))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(rhiccaDatWide$crf.artRegimen.2levels, rhiccaDatWide$vzvStatus_2levels)
## p-value = 0.4416
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.7248986 2.1164024
## sample estimates:
## odds ratio 
##   1.237598
sumFitandSum_pwv.hiv("visitNum+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia+physio.bp_sys+lims.Glucose_enrolment+lims.Cholesterol_enrolment+crf.artRegimen.2levels*cmvStatus+crf.artRegimen.2levels*vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute")
##                                                                                        term
## 1                                                                               (Intercept)
## 2                                                                                  visitNum
## 3                                                                            crf.genderMale
## 4                                                                                   crf.age
## 5                                                                      physio.bmi_enrolment
## 6                                                                             physio.bp_dia
## 7                                                                             physio.bp_sys
## 8                                                                    lims.Glucose_enrolment
## 9                                                                lims.Cholesterol_enrolment
## 10                                     crf.artRegimen.2levelsART: No change to dolutegravir
## 11                                                       cmvStatusprogression to low titres
## 12                                                      cmvStatusprogression to high titres
## 13                                                        cmvStatuspersistently high titres
## 14                                                       vzvStatusprogression to low titres
## 15                                                      vzvStatusprogression to high titres
## 16                                                        vzvStatuspersistently high titres
## 17                                                              lims.CD4_Absolute_enrolment
## 18                                                                        lims.CD4_Absolute
## 19  crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatusprogression to low titres
## 20 crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatusprogression to high titres
## 21   crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatuspersistently high titres
## 22  crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatusprogression to low titres
## 23 crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatusprogression to high titres
## 24   crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatuspersistently high titres
##         estimate    std.error    statistic         df
## 1   2.6960933219 0.4964329904  5.430931010  167.45512
## 2  -0.0139897083 0.0040250602 -3.475651912  174.87268
## 3  -0.0655520336 0.1096009825 -0.598097135  202.21080
## 4   0.0585243481 0.0070590719  8.290657637   99.78442
## 5  -0.0129748745 0.0116066203 -1.117885668  890.71522
## 6   0.0325070543 0.0062791295  5.177000179  206.41366
## 7   0.0105628624 0.0041254311  2.560426356  295.46666
## 8   0.0504509257 0.0230177153  2.191830299 1458.82451
## 9  -0.0002862432 0.0485945127 -0.005890443  234.38455
## 10 -0.1063067592 0.1352326905 -0.786102523  541.26387
## 11 -0.2413023963 0.4101445803 -0.588334963  296.81750
## 12  0.0399282171 0.2033544134  0.196347925  189.09839
## 13 -0.1285914668 0.1794056863 -0.716763607  528.24386
## 14  0.1623440984 0.2138026935  0.759317368  125.08593
## 15 -0.1159693883 0.2794586727 -0.414978670  369.33895
## 16  0.1274865394 0.1856355974  0.686756965  273.61632
## 17 -0.0002371072 0.0002886273 -0.821499582  299.36451
## 18 -0.0008768649 0.0002744481 -3.195012283  226.24239
## 19  0.0216429202 0.6992247708  0.030952737  153.45071
## 20  0.1062921741 0.2867134008  0.370726216  104.14421
## 21  0.3194278202 0.2324062794  1.374437133  508.98497
## 22 -0.0593641150 0.3005143386 -0.197541706  199.32572
## 23  0.3205949627 0.4561277128  0.702862277  165.28714
## 24 -0.2364262793 0.2485120773 -0.951367361  366.04998
##                                                 p.value rownum
## 1                    <span style="     " >0.0000</span>      1
## 2  <span style=" font-weight: bold;    " >0.0006</span>      2
## 3                    <span style="     " >0.5504</span>      3
## 4  <span style=" font-weight: bold;    " >0.0000</span>      4
## 5                    <span style="     " >0.2639</span>      5
## 6  <span style=" font-weight: bold;    " >0.0000</span>      6
## 7  <span style=" font-weight: bold;    " >0.0110</span>      7
## 8  <span style=" font-weight: bold;    " >0.0285</span>      8
## 9                    <span style="     " >0.9953</span>      9
## 10                   <span style="     " >0.4322</span>     10
## 11                   <span style="     " >0.5568</span>     11
## 12                   <span style="     " >0.8445</span>     12
## 13                   <span style="     " >0.4738</span>     13
## 14                   <span style="     " >0.4491</span>     14
## 15                   <span style="     " >0.6784</span>     15
## 16                   <span style="     " >0.4928</span>     16
## 17                   <span style="     " >0.4120</span>     17
## 18 <span style=" font-weight: bold;    " >0.0016</span>     18
## 19                   <span style="     " >0.9753</span>     19
## 20                   <span style="     " >0.7116</span>     20
## 21                   <span style="     " >0.1699</span>     21
## 22                   <span style="     " >0.8436</span>     22
## 23                   <span style="     " >0.4831</span>     23
## 24                   <span style="     " >0.3420</span>     24
sumFitandSum_cimt.hiv("+crf.gender+crf.age+physio.bmi_enrolment+physio.bp_dia_enrolment+physio.bp_sys_enrolment+lims.Glucose_enrolment+lims.Cholesterol_enrolment+crf.artRegimen.2levels*cmvStatus+crf.artRegimen.2levels*vzvStatus+lims.CD4_Absolute_enrolment+lims.CD4_Absolute_changeFromBaselineAt24Months")
##                                                                                        term
## 1                                                                               (Intercept)
## 2                                                                       cimt.cimt_enrolment
## 3                                                                            crf.genderMale
## 4                                                                                   crf.age
## 5                                                                      physio.bmi_enrolment
## 6                                                                   physio.bp_dia_enrolment
## 7                                                                   physio.bp_sys_enrolment
## 8                                                                    lims.Glucose_enrolment
## 9                                                                lims.Cholesterol_enrolment
## 10                                     crf.artRegimen.2levelsART: No change to dolutegravir
## 11                                                       cmvStatusprogression to low titres
## 12                                                      cmvStatusprogression to high titres
## 13                                                        cmvStatuspersistently high titres
## 14                                                       vzvStatusprogression to low titres
## 15                                                      vzvStatusprogression to high titres
## 16                                                        vzvStatuspersistently high titres
## 17                                                              lims.CD4_Absolute_enrolment
## 18                                           lims.CD4_Absolute_changeFromBaselineAt24Months
## 19  crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatusprogression to low titres
## 20 crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatusprogression to high titres
## 21   crf.artRegimen.2levelsART: No change to dolutegravir:cmvStatuspersistently high titres
## 22  crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatusprogression to low titres
## 23 crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatusprogression to high titres
## 24   crf.artRegimen.2levelsART: No change to dolutegravir:vzvStatuspersistently high titres
##         estimate    std.error   statistic        df
## 1  -2.448768e-02 3.833653e-02 -0.63875579 167.51374
## 2   5.359526e-02 7.101882e-02  0.75466283  50.94333
## 3  -5.432029e-03 7.995598e-03 -0.67937750 338.65251
## 4   9.087242e-04 7.585171e-04  1.19802727  29.64629
## 5  -4.865285e-04 9.485379e-04 -0.51292474 210.24100
## 6  -4.293818e-04 6.125645e-04 -0.70095774 348.38838
## 7   3.112047e-04 3.964487e-04  0.78498098 417.72815
## 8   7.503244e-04 1.769935e-03  0.42392774 401.80314
## 9  -5.334801e-03 3.721597e-03 -1.43347062 151.02365
## 10 -1.152859e-03 1.017093e-02 -0.11334843 310.58630
## 11 -8.524916e-04 2.972865e-02 -0.02867576 384.88066
## 12  3.001874e-03 1.404830e-02  0.21368239 489.02827
## 13  2.796022e-02 1.494339e-02  1.87107564  90.52844
## 14  6.881450e-03 1.583377e-02  0.43460597 115.21406
## 15  7.339145e-03 2.081300e-02  0.35262315 263.92234
## 16  3.319991e-02 1.384744e-02  2.39754894 212.78774
## 17  1.363597e-05 2.478134e-05  0.55025166  69.78186
## 18  2.862965e-05 2.438828e-05  1.17390995  84.06231
## 19 -6.189654e-03 4.716040e-02 -0.13124685 530.23410
## 20  2.224912e-02 1.965128e-02  1.13219691 242.45274
## 21 -3.186829e-02 1.944354e-02 -1.63901690  88.99383
## 22  2.900351e-02 2.367214e-02  1.22521698  91.35905
## 23 -6.428736e-03 3.236677e-02 -0.19862147 251.63579
## 24 -2.470207e-02 1.895602e-02 -1.30312521 194.20717
##                                                p.value rownum
## 1                    <span style="     " >0.524</span>      1
## 2                    <span style="     " >0.454</span>      2
## 3                    <span style="     " >0.497</span>      3
## 4                    <span style="     " >0.240</span>      4
## 5                    <span style="     " >0.609</span>      5
## 6                    <span style="     " >0.484</span>      6
## 7                    <span style="     " >0.433</span>      7
## 8                    <span style="     " >0.672</span>      8
## 9                    <span style="     " >0.154</span>      9
## 10                   <span style="     " >0.910</span>     10
## 11                   <span style="     " >0.977</span>     11
## 12                   <span style="     " >0.831</span>     12
## 13                   <span style="     " >0.065</span>     13
## 14                   <span style="     " >0.665</span>     14
## 15                   <span style="     " >0.725</span>     15
## 16 <span style=" font-weight: bold;    " >0.017</span>     16
## 17                   <span style="     " >0.584</span>     17
## 18                   <span style="     " >0.244</span>     18
## 19                   <span style="     " >0.896</span>     19
## 20                   <span style="     " >0.259</span>     20
## 21                   <span style="     " >0.105</span>     21
## 22                   <span style="     " >0.224</span>     22
## 23                   <span style="     " >0.843</span>     23
## 24                   <span style="     " >0.194</span>     24
# identify those who are virally suppressed and not-suppressed
rhiccaDatWide<-rhiccaDatWide %>%
  dplyr::mutate(
    cimtChange=cimt.cimt_24months-cimt.cimt_enrolment,
    vlSuppr_6months=ifelse(lims.HIV_Abbott_Viral_Load_0pt2ml_P_6months>150,1,0),
    vlSuppr_12months=ifelse(lims.HIV_Abbott_Viral_Load_0pt2ml_P_12months>150,1,0)
  )

# compare sub-/clinical event rates - not significant but 0 events in the small group of non-suppresseds
fisher.test(table(rhiccaDatWide$vlSuppr_6months,rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(rhiccaDatWide$vlSuppr_6months, rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT)
## p-value = 0.3779
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.000000 2.985607
## sample estimates:
## odds ratio 
##          0
fisher.test(table(rhiccaDatWide$vlSuppr_12months,rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(rhiccaDatWide$vlSuppr_12months, rhiccaDatWide$numClinEventsConfirmedPerParticipantCVDwithCIMT)
## p-value = 0.6092
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.000000 4.180156
## sample estimates:
## odds ratio 
##          0
# compare CIMT at 24 months distributions - they are different!
wilcox.test(rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_6months==0],rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_6months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_6months == 0] and rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_6months == 1]
## W = 13564, p-value = 0.09548
## alternative hypothesis: true location shift is not equal to 0
wilcox.test(rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_12months==0],rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_12months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_12months == 0] and rhiccaDatWide$cimt.cimt_24months[rhiccaDatWide$vlSuppr_12months == 1]
## W = 12766, p-value = 0.00626
## alternative hypothesis: true location shift is not equal to 0
# compare CIMT at enrolment distributions - they were already different at enrolment (at least for those still not suppressed at 12 months)
wilcox.test(rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_6months==0],rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_6months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_6months == 0] and rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_6months == 1]
## W = 21203, p-value = 0.08225
## alternative hypothesis: true location shift is not equal to 0
wilcox.test(rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_12months==0],rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_12months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_12months == 0] and rhiccaDatWide$cimt.cimt_enrolment[rhiccaDatWide$vlSuppr_12months == 1]
## W = 16887, p-value = 0.01285
## alternative hypothesis: true location shift is not equal to 0
# compare CIMT at 24 months distributions - no difference in change-from-baseline values
wilcox.test(rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_6months==0],rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_6months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_6months == 0] and rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_6months == 1]
## W = 11815, p-value = 0.9338
## alternative hypothesis: true location shift is not equal to 0
wilcox.test(rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_12months==0],rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_12months==1])
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_12months == 0] and rhiccaDatWide$cimtChange[rhiccaDatWide$vlSuppr_12months == 1]
## W = 10180, p-value = 0.9504
## alternative hypothesis: true location shift is not equal to 0
## confirming this -- not signifant when accounting for baseline CIMT in a regression model (both with 24 months CIMT and change-from-baseline CIMT as response)
summary(glm(cimt.cimt_24months~cimt.cimt_enrolment+vlSuppr_6months,data=rhiccaDatWide))
## 
## Call:
## glm(formula = cimt.cimt_24months ~ cimt.cimt_enrolment + vlSuppr_6months, 
##     data = rhiccaDatWide)
## 
## Coefficients:
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         -0.024979   0.028268  -0.884    0.377    
## cimt.cimt_enrolment  1.115494   0.054756  20.372   <2e-16 ***
## vlSuppr_6months     -0.003974   0.013330  -0.298    0.766    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.008364014)
## 
##     Null deviance: 7.6789  on 501  degrees of freedom
## Residual deviance: 4.1736  on 499  degrees of freedom
##   (394 observations deleted due to missingness)
## AIC: -971.87
## 
## Number of Fisher Scoring iterations: 2
summary(glm(cimtChange~cimt.cimt_enrolment+vlSuppr_6months,data=rhiccaDatWide))
## 
## Call:
## glm(formula = cimtChange ~ cimt.cimt_enrolment + vlSuppr_6months, 
##     data = rhiccaDatWide)
## 
## Coefficients:
##                      Estimate Std. Error t value Pr(>|t|)  
## (Intercept)         -0.024979   0.028268  -0.884   0.3773  
## cimt.cimt_enrolment  0.115494   0.054756   2.109   0.0354 *
## vlSuppr_6months     -0.003974   0.013330  -0.298   0.7658  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.008364014)
## 
##     Null deviance: 4.2128  on 501  degrees of freedom
## Residual deviance: 4.1736  on 499  degrees of freedom
##   (394 observations deleted due to missingness)
## AIC: -971.87
## 
## Number of Fisher Scoring iterations: 2
summary(glm(cimt.cimt_24months~cimt.cimt_enrolment+vlSuppr_12months,data=rhiccaDatWide))
## 
## Call:
## glm(formula = cimt.cimt_24months ~ cimt.cimt_enrolment + vlSuppr_12months, 
##     data = rhiccaDatWide)
## 
## Coefficients:
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         -0.026199   0.028649  -0.914    0.361    
## cimt.cimt_enrolment  1.117985   0.055424  20.172   <2e-16 ***
## vlSuppr_12months    -0.001892   0.014465  -0.131    0.896    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.008402589)
## 
##     Null deviance: 7.6689  on 499  degrees of freedom
## Residual deviance: 4.1761  on 497  degrees of freedom
##   (396 observations deleted due to missingness)
## AIC: -965.68
## 
## Number of Fisher Scoring iterations: 2
summary(glm(cimtChange~cimt.cimt_enrolment+vlSuppr_12months,data=rhiccaDatWide))
## 
## Call:
## glm(formula = cimtChange ~ cimt.cimt_enrolment + vlSuppr_12months, 
##     data = rhiccaDatWide)
## 
## Coefficients:
##                      Estimate Std. Error t value Pr(>|t|)  
## (Intercept)         -0.026199   0.028649  -0.914   0.3609  
## cimt.cimt_enrolment  0.117985   0.055424   2.129   0.0338 *
## vlSuppr_12months    -0.001892   0.014465  -0.131   0.8960  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.008402589)
## 
##     Null deviance: 4.2157  on 499  degrees of freedom
## Residual deviance: 4.1761  on 497  degrees of freedom
##   (396 observations deleted due to missingness)
## AIC: -965.68
## 
## Number of Fisher Scoring iterations: 2